【概述】
组合模式是将一系列对象组合成树形结构用来表示整体和部分之间的关系,组合模式的主要目的是达到,访问组合对象和访问单个对象具有一致性。这里的组合对象比较特殊,本身他可以是由其他的对象组合而成,同时,这个组合对象又可以是组成更复杂对象的一个部分。我们来举个例子来说明吧,可能更直观
【案例】
黑枣图书公司的想把图书分类以目录的形式打印出来
【OOA】
组合模式将对象组合成树形结构以表示“部分-整体”的层次结构。
设计OOD:
<说明>
1、抽象角色(MenuComponent),给参加组合的对象规定一系列接口。接口中包括管理节点的方法
在本例中如add及remove方法。MenuComponent中可以定义一些接口的默认动作。
2、树叶组件(Leaf)角色:在组合中表示叶节点对象,叶节点没有子节点。在组合中定义图元对象的行为。
在本例中为MenuItem,为菜单的具体项,不可以有子项。
3、树枝组件(Composite)角色:存储子部件。定义有子部件的那些部件的行为。在Component接口中实现与子部件有关的操作。
在本例中为Menu,为菜单项,菜单项包含了一个menuComponents数组来储存MenuItem。
【OOP】
<代码>
abstract class MenuComponent
{
public $name;
public abstract function getName();
public abstract function add(MenuComponent $menu);
public abstract function remove(MenuComponent $menu);
public abstract function getChild($i);
public abstract function show();
}
class MenuItem extends MenuComponent
{
public function __construct($name)
{
$this->name = $name;
}
public function getName(){
return $this->name;
}
public function add(MenuComponent $menu){
return false;
}
public function remove(MenuComponent $menu){
return false;
}
public function getChild($i){
return null;
}
public function show(){
echo " |-".$this->getName()."\n";
}
}
class Menu extends MenuComponent
{
public $menuComponents = array();
public function __construct($name)
{
$this->name = $name;
}
public function getName()
{
return $this->name;
}
public function add(MenuComponent $menu)
{
$this->menuComponents[] = $menu;
}
public function remove(MenuComponent $menu)
{
$key = array_search($menu, $this->menuComponents);
if($key !== false) unset($this->menuComponents[$key]);
}
public function getChild($i)
{
if(isset($this->menuComponents[$i])) return $this->menuComponents[$i];
return null;
}
public function show()
{
echo ":" . $this->getName() . "\n";
foreach($this->menuComponents as $v){
$v->show();
}
}
}
【测试用例】:
<代码>
class testDriver
{
public function run()
{
$menu1 = new Menu('文学');
$menuitem1 = new MenuItem('绘画');
$menuitem2 = new MenuItem('书法');
$menuitem3 = new MenuItem('小说');
$menuitem4 = new MenuItem('雕刻');
$menu1->add($menuitem1);
$menu1->add($menuitem2);
$menu1->add($menuitem3);
$menu1->add($menuitem4);
$menu1->show();
}
}
$test = new testDriver();
$test->run();
<输出>
小结:
组合模式解耦了客户程序与复杂元素内部结构,从而使客户程序可以向处理简单元素一样来处理复杂元素。
【常用情境】
1.想表示对象的部分-整体层次结构
2.希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。
【优点】
1、使客户端调用简单,客户端可以一致的使用组合结构或其中单个对象,用户就不必关系自己处理的是单个对象还是整个组合结构,这就简化了客户端代码。
2、更容易在组合体内加入新对象部件. 客户端不必因为加入了新的对象部件而更改代码。
【缺点 】
客户端调用简单灵活也带来组合的限制问题。
【合成模式与其它模式】
1、装饰器模式:Decorator模式经常与Composite模式一起使用。当装饰与合成一起使用时,它们通常有一个公共的父类。因此装饰必须支持具有add,remove和getChild操作的Component接口
2、享元模式:Flyweight模式让你共享组件,但不再引用他们的父部件
3、迭代器模式:Itertor可用来遍历Composite
4、访问者模式:Visitor将本来应该分布在Composite和Leaf类中的操作和行为局部化。
********************************************
* 作者:叶文涛
* 标题:Php设计模式之【组合模式Composite Pattern】
* 参考:
*《设计模式:可复用面向对象软件基础 》(美)Erich Gamma 等著
*《Head First设计模式》Eric Freeman等著
*《PHP设计模式》Aaron Saray等著,梁志敏等译(PS:翻译的是狗屁水平)
******************转载请注明网址来源 ***************