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