首页 PHP 正文
277

设计模式之组合模式

      组合模式组合多个对象形成树形结构以表示“整体-部分”的结构层次。它定义了如何将容器对象和叶子对象进行递归组合,使得客户在使用的过程中无须进行区分,可以对他们进行一致的处理。

      在使用组合模式中需要注意一点也是组合模式最关键的地方:叶子对象和组合对象实现相同的接口。这就是组合模式能够将叶子节点和对象节点进行一致处理的原因。

      虽然组合模式能够清晰地定义分层次的复杂对象,也使得增加新构件也更容易,但是这样就导致了系统的设计变得更加抽象,如果系统的业务规则比较复杂的话,使用组合模式就有一定的挑战了。

组合模式参与者:
Component :组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。 
Leaf:叶子对象。它没有子结点。 
Composite:容器对象,定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。
/**
 *统一类型与接口,叶子对象及容器对象都继承于此。
 */
abstract class Component{
    abstract public function add(Component $component);//添加子对象
    abstract public function remove(Component $component);//移除子对象
    abstract public function getChild($index);//通过索引获取某个子对象
    abstract public function operation();//对象的操作方法
    abstract public function display($depth);//此方法不是必须的,仅是用来演示。
}

/**
 *叶子对象类
 */
class Leaf extends Component{
    private $name;
    
    public function __construct($name){
        $this->name = $name;
    }
    
    public function add(Component $component){
        //由于叶子对象是不能添加容器的,所以方法为空
    }
    public function remove(Component $component){
        //方法为空,理由同上
    }
    public function getChild($index){
        return null;//叶子没有子对象
    }
    public function display($depth){
        echo str_repeat('-',$depth).$this->name.'<br>';
    }
    public function operation(){

    }
}

/**
 *容器对象类
 */
class Composite extends Component{
    private $name;
    private $list = array();
    
    public function __construct($name){
        $this->name = $name;
    }
    
    public function add(Component $component){
        if(array_search($component, $this->list) === false){
            $this->list[] = $component;
        }
    }
    public function remove(Component $component){
        if($index=array_search($component, $this->list) !== false){
            unset($this->lislc_$index);
        }
    }
    public function getChild($index){
        return $this->lislc_$index;
    }
    public function display($depth){
        echo str_repeat('-',$depth).$this->name.'<br>';
        foreach($this->list as $component){
            $component->display($depth+2);
        }
    }
    public function operation(){

    }
}

$root = new Composite('root');

$sub_root1 = new Composite('sub_root1');
$root->add($sub_root1);

$sub_root2 = new Composite('sub_root2');
$root->add($sub_root2);

$leaf_of_root = new Leaf('leaf_of_root');
$root->add($leaf_of_root);

$leaf_of_sub_root1 = new Leaf('leaf_of_sub_root1');
$sub_root1->add($leaf_of_sub_root1);

$leaf_of_sub_root2 = new Leaf('leaf_of_sub_root2');
$sub_root2->add($leaf_of_sub_root2);

$last_composite = new Composite('last_composite');
$sub_root2->add($last_composite);

$last_leaf1 = new Leaf('last_leaf1');
$last_composite->add($last_leaf1);

$last_leaf2 = new Leaf('last_leaf2');
$last_composite->add($last_leaf2);
//$last_composite->remove($last_leaf1);

$root->display(1);
/*
-root
---sub_root1
-----leaf_of_sub_root1
---sub_root2
-----leaf_of_sub_root2
-----last_composite
-------last_leaf1
-------last_leaf2
---leaf_of_root
*/

正在加载评论...