PHP设计模式—组合模式
程序员文章站
2022-04-15 19:18:03
定义: 组合模式(Composite):将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时,就应该考虑用组合模式了。 实 ......
定义:
组合模式(composite):将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。当你发现需求中是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个对象的不同,统一的使用组合结构中的所有对象时,就应该考虑用组合模式了。
实现方式:
1、透明方式:叶节点和枝节点对于外界没有什么区别,它们具备完全一致的行为接口,问题则是叶节点会有冗余方法。
2、安全方式:叶节点中的冗余代码不实现,问题则是由于不够透明,所以叶节点和枝节点将不具有相同的接口,客户端的调用需要做相应的判断,带来了不便。
代码实例:
一、透明方式实现:
// 1、抽象类component.php /** * 包含叶节点和枝节点方法的抽象类 * class component */ abstract class component { /** * @var */ protected $name; /** * component constructor. * @param $name */ public function __construct($name) { $this->name = $name; } /** * 添加叶节点或枝节点 * @param component $component * @return mixed */ abstract public function add(component $component); /** * @param $depth * @return mixed */ abstract public function display($depth); } // 2、枝节点composite.php /** * 枝节点 * class composite */ class composite extends component { /** * @var array */ protected $children = []; /** * @param component $component * @return mixed|void */ public function add(component $component) { // todo: implement add() method. $this->children[] = $component; } public function display($depth) { // todo: implement display() method. $namestr = str_repeat('-', $depth) . $this->name . '<br>'; foreach ($this->children as $component) { $namestr .= $component->display($depth + 2); } return $namestr; } } // 3、叶节点leaf.php /** * 叶节点 * class leaf */ class leaf extends component { /** * 叶节点不需要添加子节点,但为了保持叶节点和枝节点一致,代码冗余,透明方式 * @param component $component * @return mixed|string */ public function add(component $component) { // todo: implement add() method. return '叶节点不能添加子节点' . '<br>'; } public function display($depth) { // todo: implement display() method. return str_repeat('-', $depth) . $this->name . '<br>'; } }
调用:
// 生成树根root,根上长出两叶leafa和leafb $root = new composite("root"); $root->add(new leaf("leaf a")); $root->add(new leaf("leaf b")); // 根上长出分支 compositex,分支上也有两叶leafxa和leafxb $comp = new composite("composite x"); $comp->add(new leaf("leaf xa")); $comp->add(new leaf("leaf xb")); $root->add($comp); // 在compositex分支上再长出分支compositexy,分支上也有两叶leafxya和leafxyb $comp2 = new composite("composite xy"); $comp2->add(new leaf("leaf xya")); $comp2->add(new leaf("leaf xyb")); $comp->add($comp2); echo $root->display(2);
结果:
--root ----leaf a ----leaf b ----composite x ------leaf xa ------leaf xb ------composite xy --------leaf xya --------leaf xyb
二、安全方式实现:
// 1、抽象类component.php /** * 包含叶节点和枝节点方法的抽象类 * class component */ abstract class component { /** * @var */ protected $name; /** * component constructor. * @param $name */ public function __construct($name) { $this->name = $name; } /** * @param $depth * @return mixed */ abstract public function display($depth); } // 2、枝节点composite.php /** * 枝节点 * class composite */ class composite extends component { /** * @var array */ protected $children = []; /** * @param component $component * @return mixed|void */ public function add(component $component) { // todo: implement add() method. $this->children[] = $component; } public function display($depth) { // todo: implement display() method. $namestr = str_repeat('-', $depth) . $this->name . '<br>'; foreach ($this->children as $component) { $namestr .= $component->display($depth + 2); } return $namestr; } } // 3、叶节点leaf.php /** * 叶节点 * class leaf */ class leaf extends component { public function display($depth) { // todo: implement display() method. return str_repeat('-', $depth) . $this->name . '<br>'; } }
调用:
// 生成树根root,根上长出两叶leafa和leafb $root = new composite("root"); $root->add(new leaf("leaf a")); $root->add(new leaf("leaf b")); // 根上长出分支 compositex,分支上也有两叶leafxa和leafxb $comp = new composite("composite x"); $comp->add(new leaf("leaf xa")); $comp->add(new leaf("leaf xb")); $root->add($comp); // 在compositex分支上再长出分支compositexy,分支上也有两叶leafxya和leafxyb $comp2 = new composite("composite xy"); $comp2->add(new leaf("leaf xya")); $comp2->add(new leaf("leaf xyb")); $comp->add($comp2); echo $root->display(2);
结果:
--root ----leaf a ----leaf b ----composite x ------leaf xa ------leaf xb ------composite xy --------leaf xya --------leaf xyb