组合(Composite)模式的定义:有时又叫作部分-整体模式,它是一种将对象组合成树状的层次结构的模式,用来表示“部分-整体”的关系,使用户对单个对象和组合对象具有一致的访问性。

适用性

在以下情况下可以使用 Composite 模式:

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

优点 

1.组合模式使得客户端可以一致的访问单个对象或者组合对象,无需关心处理的对象是单个对象,还是组合对象,这简化了客户端的代码

2.更容易在组合中加入新的对象,客户端不会因为加入了新的对象而更改源代码,满足开闭原则

缺点

组合模式缺点 : 限制类型复杂 : 限制类型时, 比较复杂 ; 如 : 某个目录中只能包含文本文件, 使用组合模式时, 不能依赖类型系统, 施加约束, 它们都来自于节点的抽象层 ; 在这种情况下, 必须通过在运行时进行类型检查, 这样就变得比较复杂 ;

效果

  1. 定义了包含基本对象和组合对象的类层次结构。
  2. 简化客户代码。
  3. 使得更容易增加新类型的组件。
  4. 使你的设计变得更加一般化。

相关模式

  1.  Command 模式描述了如何用一个 MacroCommand Composite 类组成一些 Command 对象,并对它们进行排序。
  2. 通常 “部件-父部件” 连接用于 Responsibility of Chain 模式。
  3. Decorator 模式经常与 Composite 模式一起使用。它们通常有一个公共的父类。
  4. Flyweight 让你共享组件,但不再能引用它们的父部件。
  5. Iterator 可以用来遍历 Composite。
  6.  Visitor将本来应该分布在 Composite 和 Leaf 类中的操作和行为局部化

实现

实现方式(一):在 Component 中定义公共接口以保持透明性但损失安全性。

 在 Component 中定义 Add 和 Remove 操作需要考虑安全性和透明性。

在类层次结构的根部定义子节点管理接口的方法具有良好的透明性,但是这一方法是以安全性为代价的,因为客户有可能会做一些无意义的事情,例如在 Leaf 中 Add 对象等。

在 Composite 类中定义管理子部件的方法具有良好的安全性,但是这又损失了透明性,因为 Leaf 和 Composite 具有不同的接口。

代码:

namespace CompositePattern.Implementation1
{
  public abstract class Component
  {
    protected List<Component> _children = new List<Component>();

    public abstract void Operation();

    public virtual void Add(Component component)
    {
      _children.Add(component);
    }

    public virtual void Remove(Component component)
    {
      _children.Remove(component);
    }

    public virtual IEnumerable<Component> GetChildren()
    {
      return _children;
    }
  }

  public class Leaf : Component
  {
    public override void Operation()
    {
      // do something
    }

    public override void Add(Component component)
    {
      throw new InvalidOperationException();
    }

    public override void Remove(Component component)
    {
      throw new InvalidOperationException();
    }

    public override IEnumerable<Component> GetChildren()
    {
      throw new InvalidOperationException();
    }
  }

  public class Composite : Component
  {
    public override void Operation()
    {
      foreach (var child in _children)
      {
        child.Operation();
      }
      // may do something
    }
  }

  public class Client
  {
    public void TestCase1()
    {
      Component component1 = new Leaf();
      Component component2 = new Composite();

      component2.Add(component1);

      component1.Operation();
      component2.Operation();
    }
  }
}

 组合模式的应用场景

前面分析了组合模式的结构与特点,下面分析它适用的以下应用场景。

  1. 在需要表示一个对象整体与部分的层次结构的场合。
  2. 要求对用户隐藏组合对象与单个对象的不同,用户可以用统一的接口使用组合结构中的所有对象的场合。
Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐