1、定义安全
组合模式:将对象组合成树形结构以表示“部分-总体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具备一致性。ide
解释:简单来讲,编写一个类,该类能做用于总体,而且编写总体中的部分时也能使用该类,而不用作大的更改。this
2、UML类图及基本代码spa
基本代码:设计
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); } } }
客户端进行调用:code
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);
结果如图:component
3、透明方式和安全方式对象
基本代码中,leaf类也有add和remove方法,也就是说Component声明全部用来管理子对象的方法,实现了全部子类都具有其方法的目的。这样作的好处就是叶节点和枝节点对于外界没有区别,它们具有彻底一致的行为接口。但由于leaf不具有add和remove的功能,因此实现它是没有意义的。这种方式就是透明方式。blog
安全方式是叶节点和枝节点不具备相同的接口,因为不够透明,那么客户端调用时须要作相应的判断,带来了不便。因此在实际项目中使用安全方式和透明方式就须要视状况而定。接口
4、举例说明:
绘制一个图形,该图形由一个复杂图形和两条线段组成。能够自由的移除该图形。
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("---------------------");
调用结果:
5、优缺点及适用场景
优势:
1)组合模式使得客户端能够一致的处理对象和对象容器,既是叶节点和枝节点。
2)更容易的为组合对象添加新的组件。
3)解耦了客户端与复杂对象。
缺点:
设计更加复杂。
适用场景:
1)须要表示一个对象总体和部分的层次结构
2)用户但愿忽略组合对象和单个对象的不一样,一致的处理组合对象和单个对象。