这里我们用绘图这个例子来说明Composite模式,通过一些基本图像元素(直线、圆等)以及一些复合图像元素(由基本图像元素组合而成)构建复杂的图形树。在设计中我们对每一个对象都配备一个Draw()方法,在调用时,会显示相关的图形。可以看到,这里复合图像元素它在充当对象的同时,又是那些基本图像元素的一个容器。先看一下基本的类结构图:
图3
图中橙色的区域表示的是复合图像元素。示意性代码:
而其他作为树枝构件,实现代码如下:public abstract class Graphics { protected string _name; public Graphics(string name) { this._name = name; } public abstract void Draw(); } public class Picture : Graphics { public Picture(string name) : base(name) { } public override void Draw() { // } public ArrayList GetChilds() { //返回所有的子对象 } }
现在我们要对该图像元素进行处理:在客户端程序中,需要判断返回对象的具体类型到底是基本图像元素,还是复合图像元素。如果是复合图像元素,我们将要用递归去处理,然而这种处理的结果却增加了客户端程序与复杂图像元素内部结构之间的依赖,那么我们如何去解耦这种关系呢?我们希望的是客户程序可以像处理基本图像元素一样来处理复合图像元素,这就要引入Composite模式了,需要把对于子对象的管理工作交给复合图像元素,为了进行子对象的管理,它必须提供必要的Add(),Remove()等方法,类结构图如下:public class Line:Graphics { public Line(string name) : base(name) { } public override void Draw() { Console.WriteLine("Draw a" + _name.ToString()); } } public class Circle : Graphics { public Circle(string name) : base(name) { } public override void Draw() { Console.WriteLine("Draw a" + _name.ToString()); } } public class Rectangle : Graphics { public Rectangle(string name) : base(name) { } public override void Draw() { Console.WriteLine("Draw a" + _name.ToString()); } }
图4
示意性代码:
public abstract class Graphics { protected string _name; public Graphics(string name) { this._name = name; } public abstract void Draw(); public abstract void Add(); public abstract void Remove(); } public class Picture : Graphics { protected ArrayList picList = new ArrayList(); public Picture(string name) : base(name) { } public override void Draw() { Console.WriteLine("Draw a" + _name.ToString()); foreach (Graphics g in picList) { g.Draw(); } } public override void Add(Graphics g) { picList.Add(g); } public override void Remove(Graphics g) { picList.Remove(g); } } public class Line : Graphics { public Line(string name) : base(name) { } public override void Draw() { Console.WriteLine("Draw a" + _name.ToString()); } public override void Add(Graphics g) { } public override void Remove(Graphics g) { } } public class Circle : Graphics { public Circle(string name) : base(name) { } public override void Draw() { Console.WriteLine("Draw a" + _name.ToString()); } public override void Add(Graphics g) { } public override void Remove(Graphics g) { } } public class Rectangle : Graphics { public Rectangle(string name) : base(name) { } public override void Draw() { Console.WriteLine("Draw a" + _name.ToString()); } public override void Add(Graphics g) { } public override void Remove(Graphics g) { } }