组合模式
组合模式,将对象组合成树形结构以表示部分-整体的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
使用组合模式的时机
需求在是体现部分与整体层次的结构时,以及你希望用户可以忽略组合对象与单个的不同,统一地使用组合对象中的所有对象时,就应该考虑用组合模式了。
组合模式的好处
组合模式定义了包含基本对象和组合对象的类层次结构。基本对象可以被组合成更复杂的组合对象,这个组合对象又可以被组合,这样不断地递归下去,客户代码中任何用到基本对象的地方都可以使用组合对象了。
组合模式结构演示
抽象组件
组件为组合中的对象声明接口,在适当情况下,实现所有类共有接口的默认行为。声明一个结构用于访问和管理组件的子部件。使用Add和Remove方法来提供增加或移除树叶和树枝功能
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); }
叶子
在组合中表示叶节点对象。叶节点没有子节点,所以Add和Remove方法实现对他没有意义,但这这样做可以消除叶节点和树枝节点对象在抽象层次的区别,使他们具有完全一致的接口。这种方式叫做透明方式。
class Leaf : Component{ public Leaf(string name) : base(name) { } public override void Add(Component c) => Console.WriteLine("Cannot add to a leaf"); public override void Display(int depth) => Console.WriteLine(new string('-', depth)+name); public override void Remove(Component c) => Console.WriteLine("Cannot remove from a leaf"); }
树枝
树枝节点,能存储子部件。
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 (var c in children) c.Display(depth+2); } }
测试类
//声明树的主干,主干上两片叶子 Composite root = new Composite("root"); root.Add(new Leaf("Leaf Root-A")); root.Add(new Leaf("Leaf Root-A")); //声明一枝树枝,树枝上两片叶子 Composite comp = new Composite("Composite A"); comp.Add(new Leaf("Leaf A-A")); comp.Add(new Leaf("Leaf A-B")); //主干添加树枝 root.Add(comp); Composite comp2 = new Composite("Composite B"); comp2.Add(new Leaf("Leaf B-A")); comp2.Add(new Leaf("Leaf B-B")); root.Add(comp2); root.Display(1);//显示大树的样子 //测试结果 -root ---Leaf Root-A ---Leaf Root-A ---Composite A -----Leaf A-A -----Leaf A-B ---Composite B -----Leaf B-A -----Leaf B-B