合成模式(Composite)
模式定义
合成(Composite)模式:将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。
UML类图
- 抽象构件(component): 为参加组合的对象定义出公共的接口及其默认的行为,用来管理所有的子对象。负责对整体操作的方法有:
Operation()
Add(Component)
Remove(Component)
GetChild(int)
- 树枝构件(Composite): 抽象构建子类,并包含抽象构建类型的集合(存放下级对象)。参加组合的有下级子对象的对象,除拥有
Operation()
外,还包括整体操作方法:Add(Component)
Remove(Component)
GetChild(int)
。 - 树叶构件(Left): 抽象构建子类,没有下级子对象的对象,拥有
Operation()
即可
代码结构
public static class CompositeApp
{
public static void Run()
{
Composite root = new Composite("root");
root.Add(new Leaf("Leaf A"));
root.Add(new Leaf("Leaf B"));
Composite comp = new Composite("Composite X");
comp.Add(new Leaf("Leaf XA"));
comp.Add(new Leaf("Leaf XB"));
root.Add(comp);
root.Add(new Leaf("Leaf C"));
root.Display(1);
Console.ReadKey();
}
}
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 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 Display(int depth)
{
Console.WriteLine(new string('-', depth) + name);
foreach (Component component in _children)
{
component.Display(depth + 2);
}
}
public override void Remove(Component c)
{
_children.Remove(c);
}
}
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 Remove(Component c)
{
Console.WriteLine("Cannot remove from a leaf");
}
public override void Display(int depth)
{
Console.WriteLine(new String('-', depth) + name);
}
}
情景案例
这里以画一副画为例,一幅画有好多元素组成,每种元素都有展示方法Display(int indent);
。但有的是独立的元素(树叶节点),有的是组合元素(树枝节点)。
其实Asp.Net WebForm 中的Control就是组合机构,有个控件可以包含其它控件
public static class MainApp
{
public static void Run()
{
CompositeElement root = new CompositeElement("Picture");
root.Add(new PrimitiveElement("Red Line"));
root.Add(new PrimitiveElement("Blue Circle"));
root.Add(new PrimitiveElement("Green Box"));
CompositeElement comp = new CompositeElement("Two Circles");
comp.Add(new PrimitiveElement("Black Circle"));
comp.Add(new PrimitiveElement("White Circle"));
root.Add(comp);
PrimitiveElement pe = new PrimitiveElement("Yellow Line");
root.Add(pe);
root.Remove(pe);
root.Display(1);
Console.ReadKey();
}
}
/// <summary>
/// 画元素
/// </summary>
abstract class DrawingElement
{
protected string _name;
public DrawingElement(string name)
{
this._name = name;
}
public abstract void Add(DrawingElement d);
public abstract void Remove(DrawingElement d);
public abstract void Display(int indent);
}
/// <summary>
/// 单独元素
/// </summary>
class PrimitiveElement : DrawingElement
{
public PrimitiveElement(string name): base(name)
{
}
public override void Add(DrawingElement c)
{
Console.WriteLine("Cannot add to a PrimitiveElement");
}
public override void Remove(DrawingElement c)
{
Console.WriteLine( "Cannot remove from a PrimitiveElement");
}
public override void Display(int indent)
{
Console.WriteLine(new String('-', indent) + " " + _name);
}
}
/// <summary>
/// 组合元素
/// </summary>
class CompositeElement : DrawingElement
{
private List<DrawingElement> elements = new List<DrawingElement>();
public CompositeElement(string name) : base(name)
{
}
public override void Add(DrawingElement d)
{
elements.Add(d);
}
public override void Remove(DrawingElement d)
{
elements.Remove(d);
}
public override void Display(int indent)
{
Console.WriteLine(new String('-', indent) + "+ " + _name);
foreach (DrawingElement d in elements)
{
d.Display(indent + 2);
}
}
}