组合模式(Composite Pattern),又叫部分整体模式,是用于把一组相似的对象当作一个单一的对象。组合模式依据树形结构来组合对象,用来表示部分以及整体层次。这种类型的设计模式属于结构型模式,它创建了对象组的树形结构。
意图
将对象组合成树形结构以表示”部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
解决问题
它在我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦。
UML图
该模式包含的角色及其职责
抽象根节点(Component)
定义系统各层次对象的共有方法和属性,可以预先定义一些默认行为和属性。
树枝节点(Composite)
定义树枝节点的行为,存储子节点,组合树枝节点和叶子节点形成一个树形结构。
叶子节点(Leaf)
叶子节点对象,其下再无分支,是系统层次遍历的最小单位。
在本例子中:
优缺点
优点
缺点
应用场景
案例背景
举一个例子:一家公司的组成通常都是多个部门组成的,现在我们有一家公司有多个部门,部门里面还有很多职位,我们用这个组合模式来看看。
组织架构
使用代码把上图转换成下图的形式表达
应用场景
Component.php 抽象的公司架构(Component)
abstract class Component
{
protected $name;
/**
* Component constructor.
* @param $name
*/
public function __construct($name){
$this->name = $name;
}
public abstract function operation($depth);
public abstract function add(Component $component);
public abstract function remove(Component $component);
}
Composite.php 具体的公司部门(Composite)
class Composite extends Component
{
private $componentList;
public function operation($depth){
echo str_repeat('-', $depth) . $this->name . PHP_EOL;
foreach ($this->componentList as $component) {
$component->operation($depth + 2);
}
}
public function add(Component $component){
$this->componentList[] = $component;
}
public function remove(Component $component){
$position = 0;
foreach ($this->componentList as $child) {
++$position;
if ($child == $component) {
array_slice($this->componentList, $position, 1);
}
}
}
public function getChild(int $i){
return $this->componentList[$i];
}
}
Leaf.php 公司部门最终的职位(Leaf)
class Leaf extends Component
{
public function operation($depth){
echo str_repeat('-', $depth) . $this->name . PHP_EOL;
}
public function add(Component $component){
echo "Cannot add to a leaf".PHP_EOL;
}
public function remove(Component $component){
echo "Cannot remove from a leaf".PHP_EOL;
}
}
调用代码:
$root = new Composite("公司");
// 添加人事部门
$rs = new Composite("人事部门");
// 添加人事部门下面的职位
$rs->add(new Leaf("人事总监"));
$rs->add(new Leaf("人事主管"));
$rs->add(new Leaf("人事专员"));
$root->add($rs);
// 添加财务部门
$cw = new Composite("财务部门");
// 添加部门下面的职位
$cw->add(new Leaf("财务总监"));
$cw->add(new Leaf("会计"));
$cw->add(new Leaf("出纳"));
$root->add($cw);
$root->operation(0);
$child = $root->getChild(0);
print_r($child);
输出结果:
公司
--人事部门
----人事总监
----人事主管
----人事专员
--财务部门
----财务总监
----会计
----出纳
// 通过 getChild 获取的某个部门对象
Composite Object
(
[Composite:private] => Array
(
[0] => Leaf Object
(
[name:protected] => 人事总监
)
[1] => Leaf Object
(
[name:protected] => 人事主管
)
[2] => Leaf Object
(
[name:protected] => 人事专员
)
)
[name:protected] => 人事部门
)
如果觉得文章还不错,请把文章分享给更多的人学习,在文章中发现有误的地方也希望各位指出更正。现有误的地方也希望各位指出更正。