C#设计模式——组合模式(Composite Pattern)

一、概述

在软件开发中,我们往往会遇上类似树形结构的对象体系。即某一对象既可能在树形结构中作为叶节点存在,也可能作为分支节点存在。比如在文件系统中,文件是作为叶节点存在,而文件夹就是分支节点。在设计这类对象时,如果将叶节点和分支节点区别对待,那么在实际开发中会带来较大的复杂性。比如客户端调用时可能会频繁的使用转型操作,同时代码的可维护性和扩展性也较差。在设计中使用组合模式可以解决这一系列弊端。

二、组合模式

组合模式定义了叶节点和分支节点的一致的接口,将客户端代码与复杂的对象结构解耦,大大降低了客户端调用的复杂性。其结构图如下:

C#设计模式——组合模式(Composite Pattern)

Component定义了所有对象的共同接口,可以在Component中定义管理Component组件的接口以保证一致性,也可以将管理接口下放至Composite中以提高系统调用的安全性。

Leaf表示叶节点。

Composite定义了分支节点对象的行为,并提供一个容器用户存储其子节点。

Client通过Component来处理所有对象。

三、示例

我们利用组合模式来实现一个绘图系统。在该系统中具有Line、Circle、Picture等多种元素,其中Picture可以含有各类子元素。

首先定义Component。

 1     public abstract class Graphic

 2     {

 3         private string _name;

 4 

 5         public Graphic(string name)

 6         {

 7             _name = name;

 8         }

 9 

10         public abstract void Add(Graphic graphic);

11         public abstract void Remove(Graphic graphic);

12 

13         public virtual void Draw()

14         {

15             Console.WriteLine("Draw {0} {1}", GetType().Name, _name);

16         }

17     }

接着定义Picture对象。

 1     public class Picture : Graphic

 2     {

 3         private List<Graphic> _graphic = new List<Graphic>();

 4         public Picture(string name)

 5             : base(name)

 6         {

 7         }

 8 

 9         public override void Add(Graphic graphic)

10         {

11             _graphic.Add(graphic);

12         }

13         public override void Remove(Graphic graphic)

14         {

15             _graphic.Remove(graphic);

16         }

17         

18         public override void Draw()

19         {

20             base.Draw();

21             foreach (Graphic graphic in _graphic)

22             {

23                 graphic.Draw();

24             }

25         }

26     }

再定义Line和Circle。

 1     public class Line : Graphic

 2     {

 3         public Line(string name)

 4             : base(name)

 5         {

 6         }

 7 

 8         public override void Add(Graphic graphic)

 9         {

10             throw new Exception("Line can't add graphic");

11         }

12         public override void Remove(Graphic graphic)

13         {

14             throw new Exception("Line can't remove graphic");

15         }

16     }

17 

18     public class Circle : Graphic

19     {

20         public Circle(string name)

21             : base(name)

22         {

23         }

24 

25         public override void Add(Graphic graphic)

26         {

27             throw new Exception("Circle can't add graphic");

28         }

29         public override void Remove(Graphic graphic)

30         {

31             throw new Exception("Circle can't remove graphic");

32         }

33     }

这样就可以通过统一的Draw接口画出整幅图画。

你可能感兴趣的:(Pattern)