在使用组合模式中需要注意一点也是组合模式最关键的地方:叶子对象和组合对象实现相同的接口。这就是组合模式能够将叶子节点和对象节点进行一致处理的原因。
虽然组合模式能够清晰地定义分层次的复杂对象,也使得增加新构件也更容易,但是这样就导致了系统的设计变得更加抽象,如果系统的业务规则比较复杂的话,使用组合模式就有一定的挑战了。
组合模式参与者:
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 */