组合模式
组合模式:
将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
在数据结构里面,树结构是很重要,我们可以把树的结构应用到设计模式里面,例如多级树形菜单,文件和文件夹目录。
思维导图:
构件模式的组成:
抽象构件角色(component):是组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
树叶构件角色(Leaf):在组合树中表示叶节点对象,叶节点没有子节点。并在组合中定义图元对象的行为。
树枝构件角色(Composite):定义有子部件的那些部件的行为。存储子部件。在Component接口中实现与子部件有关的操作。
客户角色(Client):通过component接口操纵组合部件的对象。
代码:
<?php /** * 抽象构件角色(Component) * */ abstract class MenuComponent { public function add($component){} public function remove($component){} public function getName(){} public function getUrl(){} public function displayOperation(){} } /** * 树枝构件角色(Composite) * */ class MenuComposite extends MenuComponent { private $_items = array(); //存储子树枝 private $_name = null; //当前树枝的名字 //创建一个树枝,传入名字 public function __construct($name) { $this->_name = $name; } //添加一个子树枝到当前树枝 public function add($component) { $this->_items[$component->getName()] = $component; } //移除一个子树枝 public function remove($component) { $key = array_search($component,$this->_items); if($key !== false) unset($this->_items[$key]); } //得到当前树枝的子树枝 public function getItems() { return $this->_items; } //层次结构显示,注意foreach里边调用了子树枝的显示方法,这样就有层次了。 public function displayOperation($prefix='|') { if($this->getItems()) { $prefix .= ' _ _ '; }else{ $prefix .=''; } echo $this->_name, " <br/>\n"; foreach($this->_items as $name=> $item) { echo $prefix; $item->displayOperation($prefix); } } //得到当前树枝的名字 public function getName(){ return $this->_name; } } /** *树叶构件角色(Leaf) * */ class ItemLeaf extends MenuComponent { private $_name = null; private $_url = null; //实例化一个树叶,传入名字和url,这里可以根据自己的逻辑修改 public function __construct($name,$url) { $this->_name = $name; $this->_url = $url; } //树叶不能添加子树叶了,所以只有显示方法。 public function displayOperation($prefix='') { echo '<a href="', $this->_url, '">' , $this->_name, "</a><br />\n"; } //得到树叶的名字 public function getName(){ return $this->_name; } } header("Content-type: text/html; charset=utf-8"); $bj = new MenuComposite("北京"); //创建一个树枝 $cy = new ItemLeaf("朝阳区","chaoyang.com"); //创建树叶 $hd = new ItemLeaf("海淀区","haidian.com"); //创建树叶 $bj->add($cy); //添加树叶到树枝 $bj->add($hd); $yn = new MenuComposite("云南"); $zt = new MenuComposite("昭通市"); $sj = new ItemLeaf("绥江县", "suijiang.gov.cn"); $zt->add($sj); $yn->add($zt); $sd = new MenuComposite("山东"); $sd->add(new ItemLeaf("济南", "jinan.gov.cn")); $allMenu = new MenuComposite("中国"); $allMenu->add($bj); $allMenu->add($yn); $allMenu->add($sd); $allMenu->displayOperation(); // 只显示云南的 $yn->displayOperation();
总结:
组合模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以向处理简单元素一样来处理复杂元素。如果你想要创建层次结构,并可以在其中以相同的方式对待所有元素,那么组合模式就是最理想的选择。