简介
组合模式又叫对象树,将对象按照树形结构串起来,呈现出局部和整体相同的特性。
树中每个节点都由两部分组成,首先节点有自己的业务数据,其次节点内可以含有子节点集合。
比如盒子中可以放物品,也可以放其他小盒子,小盒子里又可以放物品和其他更小的盒子。
当计算盒子的物品价格时,只需要将盒子里本身的物品价格,加上小盒子里所有物品价格即可,递归处理。
角色
-
抽象节点 Component
定义一个节点的基础方法,如内部添加子节点等
-
具体节点之叶子节点 Leaf
叶子节点没有子节点
-
具体节点之非叶子节点 Composite/Container
非叶子节点,可添加子节点
或者也可以不区分是否是叶子节点,都视为节点即可
类图
图中显示,Leaf 和 Composite 都实现 Component 接口。
Composite 可添加或删除子节点,execute 则指派调用子节点的 execute 方法。
Leaf 的 execute 是真正执行逻辑的地方
代码
<?php
abstract class Component
{
protected $parent;
public function setParent(Component $parent)
{
$this->parent = $parent;
}
public function getParent(): Component
{
return $this->parent;
}
public function add(Component $component): void { }
public function remove(Component $component): void { }
public function isComposite(): bool
{
return false;
}
abstract public function operation(): string;
}
class Leaf extends Component
{
public function operation(): string
{
return "Leaf";
}
}
class Composite extends Component
{
protected $children;
public function __construct()
{
$this->children = new \SplObjectStorage();
}
public function add(Component $component): void
{
$this->children->attach($component);
$component->setParent($this);
}
public function remove(Component $component): void
{
$this->children->detach($component);
$component->setParent(null);
}
public function isComposite(): bool
{
return true;
}
public function operation(): string
{
$results = [];
foreach ($this->children as $child) {
$results[] = $child->operation();
}
return "Branch(" . implode("+", $results) . ")";
}
}
function clientCode(Component $component)
{
echo "RESULT: " . $component->operation();
}
// 只有一个叶子节点
$simple = new Leaf();
echo "Client: I've got a simple component:\n";
clientCode($simple);
echo "\n";
// 构建一个tree
$tree = new Composite();
$branch1 = new Composite();
$branch1->add(new Leaf());
$branch1->add(new Leaf());
$branch2 = new Composite();
$branch2->add(new Leaf());
$tree->add($branch1);
$tree->add($branch2);
echo "Client: Now I've got a composite tree:\n";
clientCode($tree);
// 合并两个tree
function clientCode2(Component $component1, Component $component2)
{
if ($component1->isComposite()) {
$component1->add($component2);
}
echo "RESULT: " . $component1->operation();
}
echo "\n";
echo "Client: I don't need to check the components classes even when managing the tree:\n";
clientCode2($tree, $simple);
output:
Client: I've got a simple component:
RESULT: Leaf
Client: Now I've got a composite tree:
RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf))
Client: I don't need to check the components classes even when managing the tree:
RESULT: Branch(Branch(Leaf+Leaf)+Branch(Leaf)+Leaf)
Top comments (0)