- 设计模式(10):组合模式(Composite Pattern)
-
-
-
组合模式(Composite Pattern)
-
-
定义
-
组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
-
-
组合模式(Composite Pattern)结构图
-
-
-
Component为组合中的对象声明接口,在适当的情况下,实现所有类共有接口的默认行为。声明一个接口用于访问和管理Component的子部件
-
abstract class Component
{
protected string name;
public Component(string name)
{
this.name=name;
}
public abstract void Add(component c);//通常都用Add和Remove方法来提供增加或移出树叶或树枝的功能
public abstract void Remove(Component c);
public abstract void Display(in depth);
}
-
- Leaf在组合中表示叶节点对象,叶节点没有子节点
-
class Leaf:Component
{
public Leaf(string name):base(name)
{}
public override void Add(Component c)//由于叶节点没有再增加分枝和树叶,所以Add和Remove方法实现
{
Console.WriteLine("Cannot add to a leaf");它没有意义,但这样可以消除叶节点和枝节点对象在抽象层次的区别
} 它们具备完全一致的接口
public override void Remove(Component c)
{
Console.WriteLine("Cannot remove to a leaf");
}
public override void Display(int depth)
{
//叶节点的具体方法,此处是显示其名称和级别
Console.WriteLine();
}
}
-
- Composite定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关的操作,比如增加Add
和删除Remove
-
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);
}
}
}
-
- 客户端代码,能通过Component接口操作组合部件的对象
-
static void Main(string[] args)
{
Component root=new Component("root");
root.Add(new Leaf("Leaf A"));//生成树根root,根上长出两叶
root.Add(new Leaf("Leaf B"));//LeafA与LeafB
Composite comp=new Composite("Componsite X");
comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
root.Add(comp);
Composite comp2=new Composite("Composite XY");
comp2.Add(new Leaf("Leaf XYA"));
comp2.Add(new Leaf("Leaf XYB"));
comp.Add(comp2);
//根部又长出两页LeafC和LeafD,可惜LeafD没有长牢,被风吹走了
root.Add(new Leaf("Leaf c"));
Leaf leaf=new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
root,Display(1);//显示大树的样子
}
-
- 显示结果:
-
-root
---leaf A
---leaf B
---Composite X
-----Leaf XA
-----Leaf XB
-----Composite XY
-------Composite XYA
-------Composite XYB
---Leaf c
-
- 适用场景
当需求中是体现部分与整体层次的结构时,以及希望用户可以忽略组合对象 与单个对象的不同时,统一地使用组合结构中的所有对象时,就应该考虑用组合模式了
组合模式的优点:
组合模式定义了包含基本对象和组合对象的类层次结构。 基本对象可以被组合成更复杂的组合 对象,而这个组合对象又可以被组合,这样不断地递归下去,客户代码中,任何用到基本对象的 地方都可以使用组合对象了。 用户不用关心到底是处理一个叶节点还是处理一个组合组件, 也就是用不着为定义组合而写一些选择判断语句了,简单地说就是组合模式让客户可以一致地使用 组合结构和单个对象。
透明方式:也就是说在Component中声明所有用来管理子对象的方法中,其中包括Add、Remove 等。这样实现Component接口的所有子类都具备了Add和Remove。这样做的好处就是叶节点 和枝节点对于外界没有区别,它们具备完全一致的行为接口。但问题也很明显,因为Leaf 类本身不具备Add()、Remove()方法的功能,所以实现它是没有意义的。
安全方式:也就是在Component接口中不去声明Add和Remove方法,那么子类的Leaf也不需要去实现它,而是在 Composite声明所有用来管理子类对象的方法。不过由于不透明,所以树叶和树枝将不具有相同的接口, 客户端的调用需要做相应的判断,带来了不便 。