写点什么

结构型设计模式 - 组合 (对象树) Composite

作者:菜皮日记
  • 2023-09-08
    北京
  • 本文字数:1834 字

    阅读完需:约 6 分钟

简介

组合模式又叫对象树,将对象按照树形结构串起来,呈现出局部和整体相同的特性。

树中每个节点都由两部分组成,首先节点有自己的业务数据,其次节点内可以含有子节点集合。

比如盒子中可以放物品,也可以放其他小盒子,小盒子里又可以放物品和其他更小的盒子。

当计算盒子的物品价格时,只需要将盒子里本身的物品价格,加上小盒子里所有物品价格即可,递归处理。

类图

角色

  • 抽象节点 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);
// 合并两个treefunction 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: LeafClient: 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)
复制代码


用户头像

菜皮日记

关注

全干程序员 2018-08-08 加入

还未添加个人简介

评论

发布
暂无评论
结构型设计模式-组合(对象树) Composite_设计模式_菜皮日记_InfoQ写作社区