
·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> 设计模式(14)---组合模式
一、定义
组合模式:将对象组合成树形结构以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
解释:简单来说,编写一个类,该类能作用于整体,并且编写整体中的部分时也能使用该类,而不用做大的更改。
二、UML类图及基本代码

基本代码:
abstract class Component
{
PRotected string name;
public Component(string name)
{
this.name = name;
}
public abstract void Add(Component component);
public abstract void Remove(Component component);
public abstract void Display(int depth);
}
class Leaf : Component
{
public Leaf(string name)
: base(name)
{ }
public override void Add(Component component)
{
Console.WriteLine("cannot add to a leaf");
}
public override void Remove(Component component)
{
Console.WriteLine("cannot remove to a leaf");
}
public override void Display(int depth)
{
Console.WriteLine(new string('-', depth) + name);
}
}
class Composite : Component
{
private IList<Component> children = new List<Component>();
public Composite(string name)
: base(name)
{ }
public override void Add(Component component)
{
children.Add(component);
}
public override void Remove(Component component)
{
children.Remove(component);
}
public override void Display(int depth)
{
Console.WriteLine(new string('-', depth) + name);
foreach (Component component in children)
{
component.Display(depth + 2);
}
}
}
客户端进行调用:
Composite root = new Composite("root");
root.Add(new Leaf("leaf A"));
root.Add(new Leaf("leaf B"));
Composite composite = new Composite("Composite X");
composite.Add(new Leaf("leaf XA"));
composite.Add(new Leaf("leaf XB"));
root.Add(composite);
Composite composite2 = new Composite("Composite XY");
composite2.Add(new Leaf("leaf XYA"));
composite2.Add(new Leaf("leaf XYB"));
composite.Add(composite2);
root.Add(new Leaf("leaf C"));
Leaf leaf = new Leaf("Leaf D");
root.Add(leaf);
root.Remove(leaf);
root.Display(1);
View Code
结果如图:

三、透明方式和安全方式
基本代码中,leaf类也有add和remove方法,也就是说Component声明所有用来管理子对象的方法,实现了所有子类都具备其方法的目的。这样做的好处就是叶节点和枝节点对于外界没有区别,它们具备完全一致的行为接口。但因为leaf不具备add和remove的功能,所以实现它是没有意义的。这种方式就是透明方式。
安全方式是叶节点和枝节点不具有相同的接口,由于不够透明,那么客户端调用时需要做相应的判断,带来了不便。所以在实际项目中使用安全方式和透明方式就需要视情况而定。
四、举例说明:
绘制一个图形,该图形由一个复杂图形和两条线段组成。可以自由的移除该图形。
public abstract class Graphics
{
public string Name { get; set; }
public Graphics(string name)
{
this.Name = name;
}
public abstract void Draw();
public abstract void Add(Graphics graphics);
public abstract void Remove(Graphics graphics);
}
public class Line : Graphics
{
public Line(string name)
: base(name)
{ }
public override void Draw()
{
Console.WriteLine("画 " + Name);
}
public override void Add(Graphics graphics)
{
throw new Exception("不能向简单图形line添加图形");
}
public override void Remove(Graphics graphics)
{
throw new Exception("不能向简单图形line移除图形");
}
}
public class Circle : Graphics
{
public Circle(string name)
: base(name)
{ }
public override void Draw()
{
Console.WriteLine("画 " + Name);
}
public override void Add(Graphics g)
{
throw new Exception("不能向简单图形Circle添加其他图形");
}
public override void Remove(Graphics g)
{
throw new Exception("不能向简单图形Circle移除其他图形");
}
}
public class ComplexGraphics : Graphics
{
private IList<Graphics> complexGraphicsList = new List<Graphics>();
public ComplexGraphics(string name)
: base(name)
{ }
public override void Draw()
{
foreach (Graphics g in complexGraphicsList)
{
g.Draw();
}
}
public override void Add(Graphics graphics)
{
complexGraphicsList.Add(graphics);
}
public override void Remove(Graphics graphics)
{
complexGraphicsList.Remove(graphics);
}
}
客户端调用:
ComplexGraphics complexGraphics = new ComplexGraphics("一个复杂图形和两条线段组成的复杂图形");
complexGraphics.Add(new Line("线段A"));
ComplexGraphics complexGraphics2 = new ComplexGraphics("一个圆和一条线组成的复杂图形");
complexGraphics2.Add(new Circle("圆"));
complexGraphics2.Add(new Line("线段B"));
complexGraphics.Add(complexGraphics2);
Line line = new Line("线段C");
complexGraphics.Add(line);
Console.WriteLine("复杂图形的绘制如下:");
Console.WriteLine("----------------------");
complexGraphics.Draw();
Console.WriteLine("复杂图形的绘制完成");
Console.WriteLine("----------------------");
complexGraphics.Remove(line);
Console.WriteLine("移除线段C后,复杂图形的绘制如下:");
Console.WriteLine("---------------------");
complexGraphics.Draw();
Console.WriteLine("复杂图形绘制完成");
Console.WriteLine("---------------------");
View Code
调用结果:

五、优缺点及适用场景
优点:
1)组合模式使得客户端可以一致的处理对象和对象容器,既是叶节点和枝节点。
2)更容易的为组合对象添加新的组件。
3)解耦了客户端与复杂对象。
缺点:
设计更加复杂。
适用场景:
1)需要表示一个对象整体和部分的层次结构
2)用户希望忽略组合对象和单个对象的不同,一致的处理组合对象和单个对象。