Design Patterns - Composite

Composite(组合) — 对象结构型模式

当有将对象组合成树形结构来表示“部分 - 整体” 的层次结构时,我们可以使用 Composite 模式,Composite 使得用户对单个对象和组合对象的使用具有一致性。

适用场景

  1. 你想表示对象的部分 - 整体层次结构。
  2. 你想用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的对象。

UML 图

在这里插入图片描述

效果

  1. 定义了包含基本对象和组合对象的类层次机构:基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去。客户代码中,任何用到基本对象的地方都可以使用组合对象。
  2. 简化客户代码:客户可以一致的使用组合结构和单个对象。通常用户不知道(也不关心)处理的是一个叶结点还是一个组合组件。这就简化了客户代码,因为在定义组合的那些类中不需要写一些充斥着选择语句的函数。
  3. 使得更容易增加新类型的组件:新定义的 Composite 或 Leaf 子类自动地与已有的结构的客户代码一起工作,客户程序不需要因新的 Component 类而改变。
  4. 使你的设计变得更加一般化:容易增加新组件也会产生一些问题,那就是很难限制组合中的组件。有时你希望一个组合只能有某些特定的组件。使用 Composite 时,你不能依赖类型系统施加这些约束,而必须在运行时进行检查。

几个问题

  1. 最大化 Component 接口:
    Composite 模式的目的之一是使得用户不知道他们正在使用具体的 Leaf 类和 Composite 类。为了达到这一目的,Composite 类应为 Leaf 和 Composite 类尽可能多定义一些公共操作。Composite 类通常为这些操作提供缺省的实现,而 Leaf 和Composite 子类可以对它们进行重定义。
    然而,这个目标有时可能会与类层次结构设计原则相冲突,该原则规定:一个类只能定义那些对它的子类有意义的操作。有许多 Component 所支持的操作对 Leaf 类似乎没有什么意义,那么 Component 怎样为它们提供一个缺省的操作呢?
    即把 Leaf 看成一个没有子节点的 Component,就可以在 Component 类中定义一个缺省的操作。

  2. 声明管理子部件的操作:
    虽然 Composite 类实现了 Add 和 Remove 操作用于管理子部件,但在 Composite 模式中一个重要的问题是:在 Composite 类层次结构中那些类声明这些操作。我们是应该在 Component 中声明这些操作,并使这些操作对 Leaf 类有意义,还是只应该在 Composite 和它的子类中声明并定义这些操作呢?
    这需要在安全性和透明性之间做出选择。

    • 在类层次结构的根部定义子节点管理接口的方法具有良好的透明性,因为你可以一致的使用所有的组件,但是这一方法是以安全性为代价的,因为客户有可能会做一些无意义的事情,例如在 Leaf 中增加和删除对象等。
    • 在 Composite 类中定义管理子部件的方法具有良好的安全性,因为在像 C++ 这样的静态类型语言中,在编译时任何从 Leaf 中增加或删除对象的尝试都会被发现。但这又损失了透明性,因为 Leaf 和 Composite 具有不同的接口。

    在这一模式中,相对于安全性,我们比较强调透明性。如果你选择了安全性,有时你可能会丢失类型信息,并且不得不将一个组件转换成一个组合。这样的类型转换必定不是安全的。

示例

# coding=utf-8
class Component:
    def __init__(self, name):
        self.name = name

    def add(self, comp):
        pass

    def remove(self, comp):
        pass

    def display(self, depth):
        pass

class Leaf(Component):
    def display(self, depth):
        strtemp = ''
        for i in range(depth):
            strtemp += '---'
        print(strtemp + self.name)

class Composite(Component):
    def __init__(self, name):
        super(Composite, self).__init__(name)
        self.children = []

    def add(self, comp):
        self.children.append(comp)

    def remove(self, comp):
        self.children.remove(comp)

    def display(self, depth):
        strtemp = ''
        for i in range(depth):
            strtemp += '---'
        print(strtemp + self.name)
        for comp in self.children:
            comp.display(depth + 2)

client

if __name__ == "__main__":
    root = Composite('根')

    root.add(Leaf('叶1a'))
    root.add(Leaf('叶1b'))
    root.add(Leaf('花1a'))
    root.add(Leaf('花1b'))
    comp1a = Composite('枝1a')
    comp1b = Composite('枝1b')
    root.add(comp1a)
    root.add(comp1b)

    comp1a.add(Leaf('叶2a'))
    comp1a.add(Leaf('叶2b'))
    comp1a.add(Leaf('花2a'))
    comp1a.add(Leaf('花2b'))
    comp2a = Composite('枝2a')
    comp1a.add(comp2a)

    comp1b.add(Leaf('叶2a'))
    comp1b.add(Leaf('花2a'))

    comp2a.add(Leaf('叶3a'))
    comp2a.add(Leaf('花3a'))
    comp3a = Composite('枝3a')
    comp2a.add(comp3a)

    comp3a.add(Leaf('叶4a'))
    comp3a.add(Leaf('花4a'))
    root.display(1)
"""
output:
---根
---------叶1a
---------叶1b
---------花1a
---------花1b
---------枝1a
---------------叶2a
---------------叶2b
---------------花2a
---------------花2b
---------------枝2a
---------------------叶3a
---------------------花3a
---------------------枝3a
---------------------------叶4a
---------------------------花4a
---------枝1b
---------------叶2a
---------------花2a

Process finished with exit code 0

"""
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值