设计模式-08.COMPOSITE(组合)— 对象结构型模式

1 意图

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

2 别名

3 动机

在绘图编辑器和图形捕捉系统这样的图形应用程序中,用户可以使用简单的组件创建复杂的图表。用户可以组合多个简单组件以形成一些较大的组件,这些组件又可以组合成更大的组件。一个简单的实现方法是为 Text 和 Line 这样的图元定义一些类,另外定义一些类作为这些图元的容器类(Container)。问题:使用这些类的代码必须区别对待图元对象与容器对象,而实际上大多数情况下用户认为它们是一样的。
图一

4 适用性

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

5 结构

图二

6 参与者

  • Component(Graphic)
    • 为组合中的对象声明接口。
    • 在适当的情况下,实现所有类共有接口的缺省行为。
    • 声明一个接口用于访问和管理 Component 的子组件。
    • (可选)在递归结构中定义一个接口,用于访问一个父部件,并在合适的情况下实现它。
  • Leaf(Rectangle、Line、Text 等)
    • 在组合中表示叶节点对象,叶节点没有子节点。
    • 在组合中定义图元对象的行为。
  • Composite(Picture)
    • 定义有子部件的那些部件的行为。
    • 存储子部件。
    • 在 Component 接口中实现与子部件有关的操作。
  • Client
    • 通过 Component 接口操纵组合部件的对象。

7 协作

用户使用 Component 类接口与组合结构中的对象进行交互。如果接收者是一个叶节点 ,则直接处理请求。如果接收者是 Composite , 它通常将请求发送给它的子部件,在转发请求之前与/或之后可能执行一些辅助操作。

8 效果

  • 定义了包含基本对象和组合对象的类层次结构
  • 简化客户代码
  • 使得更容易增加新类型的组件
  • 使你的设计变得更加一般化
  • 子部件排序

9 实现

  • 显式的父部件引用
  • 共享组件
  • 最大化 Component 接口
  • 声明管理子部件的操作(透明性 or 安全性)
  • Component 是否应该实现一个 Component 列表
  • 应该由谁删除 Component
  • 存贮组件最好用哪一种数据结构(列表、树、数组和 hash 表,效率)

10 代码示例

  • Component

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Component
    {
    public abstract void Operation();

    public virtual void Add(Component component)
    {
    //默认实现,Leaf不需要复写,Composite需要复写
    }

    public virtual void Remove(Component component)
    {
    //默认实现,Leaf不需要复写,Composite需要复写
    }

    public virtual Component GetChild(int index)
    {
    //默认实现,Leaf不需要复写,Composite需要复写
    }
    }
  • Leaf(Rectangle、Line、Text 等)

    1
    2
    3
    4
    5
    6
    7
    class Leaf:Component
    {
    public override void Operation()
    {
    Console.WriteLine("Leaf");
    }
    }
  • Composite(Picture)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    class Composite:Component
    {
    private List<Component> children=new List<Component>();

    public override void Operation()
    {
    foreach(var component in children)
    {
    component.Operation();
    }
    }

    public new void Add(Component component)
    {
    children.Add(component);
    }

    public new void Remove(Component component)
    {
    children.Add(component);
    }

    public new Component GetChild(int index)
    {
    return children[index];
    }
    }
  • Client

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Client
    {
    public static void Main(string[] args)
    {
    Component leaf=new Leaf();
    leaf.Operation();

    Component composite=new Composite();
    composite.Add(leaf);
    composite.Operation();
    }
    }

11 已知应用

MVC 中的 View。

12 相关模式

  • 通常部件 - 父部件连接用于 Responsibility of Chain 模式。
  • Decorator 模式经常与 Composite 模式一起使用。当装饰和组合一起使用时,它们通常有一个公共的父类。因此装饰必须支持具有 Add、Remove 和 GetChild 操作的 Component。
  • Flyweight 让你共享组件,但不再能引用他们的父部件。
  • Itertor 可用来遍历 Composite。
  • Visitor 将本来应该分布在 Composite 和 Leaf 类中的操作和行为局部化。
坚持原创技术分享,您的支持将鼓励我继续创作!