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接口画出整幅图画。

原文地址:https://www.cnblogs.com/saville/p/2765574.html