定义

  1. 将对象组合成树形结构来表示“部分 - 整体”的层次结构。
  2. 组合结构使得用户对单个对象和组合对象的使用保持一致性。
  3. 整体 和 部分 可以 一致对待 的问题

使用场景

  1. 部分、整体场景
  2. 文件夹管理
  3. 公司分公司部门统一管理OA

代码实现

abstract class Component
{
    protected string name;

    public Component(string name)
    {
        this.name = name;
    }
    
    public abstract void Add(Component c);
    public abstract void Remove(Component c);
    public abstract void Display(int depth);

}

class Leaf: Component
{
    public Leaf(string name):base(name){ }

    public override void Add(Component c)
    {
        Console.WriteLine("Cannot add to leaf");
    }
    
    public override void Remove(Component c)
    {
        Console.WriteLine("Cannot remove from a leaf");
    }
    
    public override void Display(int depth)
    {
        Console.WriteLine(new string('-', depth) + name);
    }

}

class Composite: Component
{
    private List<Component> children = new List<Component>();

    public Composite(string name):base(name) { }
    
    public override void Add(Component c)
    {
        children.Add(c);
    }
    
    public override void Remove(Component c)
    {
         children.Remove(c);
    }
    
    public override void Display(int depth)
    {
        Console.WriteLine(new string('-', depth) + name);
    
        foreach(Component component in children)
        {
               component.Display(depth + 2);
        }
    }

}


void Main()
{
     Composite root = new Composite("root");
     root.Add(new Leaf("Leaf A"));
     root.Add(new Leaf("Leaf B"));
     

     Composite comp = new Composite("Comp X");
     comp.Add(new Leaf("Leaf XA"));
     comp.Add(new Leaf("Leaf XB"));
    
    Composite comp1 = new Composite("Comp XY");
    var leaf = new Leaf("Leaf XYA");
    comp1.Add(leaf);
    comp1.Remove(leaf);
    
    comp.Add(comp1);
    
     root.Add(comp);     
     
     root.Display(1);

}

透明模式 与 安全模式

  1. 透明模式是 枝节点 和 叶节点 都存在 Add 和 Remove 方法,而叶节点不需要实现这两个方法
  2. 安全模式是 不在Component 中声明 Add 和 Remove 方法,而放到枝节点中,这样叶节点就不用实现 Add 和 Remove 方法,但是由于不够透明,客户端调用需要做相应的判断

优点

  1. 高层模块调用简单,节点可以自由添加
  2. 组合模式使得客户端代码可以一致地处理单个对象和组合对象,无须关心自己处理的是单个对象,还是组合对象,这简化了客户端代码

缺点

  1. 叶节点类和枝节点类都是实现类而不是接口类,违反了依赖倒置原则
  2. 不容易用继承的方法来增加构件的新功能
  3. 不容易限制容器中的构件
  4. 设计较复杂,客户端需要花更多时间理清类之间的层次关系