19
05月
2020
组合模式
模式定义
组合模式(Composite),有时候又叫做部分-整体模式,用于将对象组合成树形结构以表示“部分-整体”的层次关系。组合模式使得用户对单个对象和组合对象的使用具有一致性。
组合模式的优势
使我们在树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
组合模式让你可以优化处理递归或分级数据结构。
代码示例
Composite\CompanyBase.class.php
<?php namespace Composite; abstract class CompanyBase { protected $name; public function __construct($name) { $this->name = $name; } public function getName() { return $this->name; } abstract function add(CompanyBase $c); abstract function remove(CompanyBase $c); abstract function show($deep); abstract function work($deep); }
Composite\Company.class.php
<?php namespace Composite; class Company extends CompanyBase { protected $item = []; public function add(CompanyBase $c) { $nodeName = $c->getName(); if(!isset($this->item[$nodeName])){ $this->item[$nodeName] = $c; } else { throw new Exception("该节点已存在,节点名称:" . $nodeName); } } function remove(CompanyBase $c) { $nodeName = $c->getName(); if(isset($this->item[$nodeName])) { unset($this->item[$nodeName]); } else { throw new Exception("该节点已存在,节点名称:" . $nodeName); } } function show($deep = 0) { echo str_repeat("-", $deep) . $this->name; echo "\n"; foreach ($this->item as $value){ $value->show($deep + 4); } } function work($deep = 0) { foreach ($this->item as $value){ echo str_repeat(" ", $deep) . "[{$this->name}]\n"; $value->work($deep + 2); } } }
Composite\HumanResources.class.php
<?php namespace Composite; class HumanResources extends CompanyBase { function add(CompanyBase $c) { throw new Exception("该节点不能增加节点"); } function remove(CompanyBase $c) { throw new Exception("该节点下无子节点"); } function show($deep = 0) { echo str_repeat("-",$deep).$this->name; echo "\n"; } function work($deep = 0) { echo str_repeat(" ",$deep)."人力资源部门的工作是为公司招聘人才"; echo "\n"; } }
Composite\Commerce.class.php
<?php namespace Composite; class Commerce extends CompanyBase { function add(CompanyBase $c) { throw new Exception("该节点下不能增加节点"); } function remove(CompanyBase $c) { throw new Exception("该节点下无子节点"); } function show($deep = 0) { echo str_repeat("-",$deep).$this->name; echo "\n"; } function work($deep = 0) { echo str_repeat(" ",$deep)."商务部门的工作是为公司赚取利润"; echo "\n"; } }
Composite\CompositeTest.php
<?php spl_autoload_register(function ($className){ $className = str_replace("\\", "/", $className); include $className . ".class.php"; }); use Composite\Company; use Composite\HumanResources; use Composite\Commerce; $company = new Company("公司"); $human = new HumanResources("人力资源部"); $commerce = new Commerce("商务部"); $company->add($human); $company->add($commerce); $company1 = new Company("分公司1"); $company1->add($human); $company1->add($commerce); $company->add($company1); $company2 = new Company("分公司2"); $company2->add($human); $company2->add($commerce); $company->add($company2); $company->show(); echo "\n\n"; $company->work();
测试示例:
php Composite/CompositeTest.php 输出: 公司 ----人力资源部 ----商务部 ----分公司1 --------人力资源部 --------商务部 ----分公司2 --------人力资源部 --------商务部 [公司] 人力资源部门的工作是为公司招聘人才 [公司] 商务部门的工作是为公司赚取利润 [公司] [分公司1] 人力资源部门的工作是为公司招聘人才 [分公司1] 商务部门的工作是为公司赚取利润 [公司] [分公司2] 人力资源部门的工作是为公司招聘人才 [分公司2] 商务部门的工作是为公司赚取利润
总结
组合模式,就是在一个对象中包含其他对象,这些被包含的对象可能是终点对象(不再包含别的对象),也有可能是非终点对象(其内部还包含其他对象,或叫组对象),我们将对象称为节点,即一个根节点包含许多子节点,这些子节点有的不再包含子节点,而有的仍然包含子节点,以此类推。很明显,这是树形结构,终结点叫叶子节点,非终节点(组节点)叫树枝节点,第一个节点叫根节点。同时也类似于文件目录的结构形式:文件可称之为终节点,目录可称之为非终节点(组节点)。
代码地址:https://github.com/798256478/design-patterns/tree/master/Composite