组合模式
组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。掌握组合模式的重点是要理解清楚 “部分/整体” 还有 ”单个对象“ 与 “组合对象” 的含义。
模式结构
- Component :组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component子部件。
- Leaf:叶子对象。叶子结点没有子结点。
- Composite:容器对象,定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。
结构图
PHP代码实现
<?php
// 组件接口声明了组合中简单和复杂对象的通用操作
interface Component {
public function operation(): string;
}
// 叶子组件代表组合的末端对象。一个叶子对象没有子对象。
// 通常是这些对象执行实际的工作,而复合对象只是委托给它们的子组件。
class Leaf implements Component {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function operation(): string {
return "Leaf " . $this->name . " performs an operation.\n";
}
}
// 容器组件包含复杂组件,可以包含叶子节点或其他容器节点。
class Composite implements Component {
protected $children = [];
public function add(Component $component): void {
$this->children[] = $component;
}
public function remove(Component $component): void {
$this->children = array_filter($this->children, function ($child) use ($component) {
return $child !== $component;
});
}
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();
// ...
}
// 这样可以构建简单的组件
$leaf = new Leaf("Leaf 1");
echo "Client: I've got a simple component:\n";
clientCode($leaf);
echo "\n\n";
// 以及更复杂的组合
$tree = new Composite();
$branch1 = new Composite();
$branch1->add(new Leaf("Leaf 2"));
$branch1->add(new Leaf("Leaf 3"));
$branch2 = new Composite();
$branch2->add(new Leaf("Leaf 4"));
$tree->add($branch1);
$tree->add($branch2);
echo "Client: Now I've got a composite tree:\n";
clientCode($tree);
echo "\n\n";
// 你可以管理组合对象的生命周期,就像你是管理一个单一组件一样
echo "Client: I don't need to check the components classes even when managing the tree:\n";
clientCode($tree);