C#设计模式之九组合模式(Composite Pattern)【结构型】
一、引言 ?????? 二、组合模式的详细介绍 2.1、动机(Motivate) ???? 客户代码过多地依赖于对象容器(对象容器是对象的容器,细细评味)复杂的内部实现结构,对象容器内部实现结构(而非抽象接口)的变化将引起客户代码的频繁变化,带来了代码的维护性、扩展性等方面的弊端。如何将“客户代码与复杂的对象容器结构”解耦?如何让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器? 2.2、意图(Intent) ???? 将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。 ? ??? ?——? 《设计模式》GoF 2.3、结构图(Structure) ????? 2.4、模式的组成 ?? ? ??? 组合模式中涉及到三个角色: ??? (1)、抽象构件角色(Component):这是一个抽象角色,它给参加组合的对象定义出了公共的接口及默认行为,可以用来管理所有的子对象(在透明式的组合模式是这样的)。在安全式的组合模式里,构件角色并不定义出管理子对象的方法,这一定义由树枝结构对象给出。 ??? (2)、树叶构件角色(Leaf):树叶对象是没有下级子对象的对象,定义出参加组合的原始对象的行为。(原始对象的行为可以理解为没有容器对象管理子对象的方法,或者 【原始对象行为】+【管理子对象的行为(Add,Remove等)】=面对客户代码的接口行为集合) ??? (3)、树枝构件角色(Composite):代表参加组合的有下级子对象的对象,树枝对象给出所有管理子对象的方法实现,如Add、Remove等。 ?? 组合模式实现的最关键的地方是——简单对象和复合对象必须实现相同的接口。这就是组合模式能够将组合对象和简单对象进行一致处理的原因。 2.5、组合模式的具体代码实现 ??????? 组合模式有两种实现方式,一种是:透明式的组合模式,另外一种是:安全式的组合模式。在这里我就详细说一下何为“透明式”,何为“安全式”。所谓透明式是指“抽象构件角色”定义的接口行为集合包含两个部分,一部分是叶子对象本身所包含的行为(比如Operation),另外一部分是容器对象本身所包含的管理子对象的行为(Add,Remove)。这个抽象构件必须同时包含这两类对象所有的行为,客户端代码才会透明的使用,无论调用容器对象还是叶子对象,接口方法都是一样的,这就是透明,针对客户端代码的透明,但是也有他自己的问题,叶子对象不会包含自己的子对象,为什么要有Add,Remove等类似方法呢,调用叶子对象这样的方法可能(注意:我这里说的是可能,因为有些人会把这些方法实现为空,不做任何动作,当然也不会有异常抛出了,不要抬杠)会抛出异常,这样就不安全了,然后人们就提出了“安全式的组合模式”。所谓安全式是指“抽象构件角色”只定义叶子对象的方法,确切的说这个抽象构件只定义两类对象共有的行为,然后容器对象的方法定义在“树枝构件角色”上,这样叶子对象有叶子对象的方法,容器对象有容器对象的方法,这样责任很明确,当然调用肯定不会抛出异常了。大家可以根据自己的情况自行选择是实现为“透视式”还是“安全式”的,以下我们会针对这两种情况都有实现,具体实现如下: 1 namespace 透明式的组合模式的实现 2 { 3 /// <summary> 4 /// 该抽象类就是文件夹抽象接口的定义,该类型就相当于是抽象构件Component类型 5 </summary> 6 public abstract class Folder 7 { 8 //增加文件夹或文件 9 void Add(Folder folder); 10 11 删除文件夹或者文件 12 Remove(Folder folder); 13 14 打开文件或者文件夹--该操作相当于Component类型的Operation方法 15 Open(); 16 } 17 18 19 该Word文档类就是叶子构件的定义,该类型就相当于是Leaf类型,不能在包含子对象 20 21 sealed Word : Folder 22 23 24 override Add(Folder folder) 25 { 26 throw new Exception("Word文档不具有该功能"); 27 } 28 29 30 Remove(Folder folder) 31 32 33 34 35 打开文件--该操作相当于Component类型的Operation方法 36 Open() 37 38 Console.WriteLine(打开Word文档,开始进行编辑39 40 41 42 43 SonFolder类型就是树枝构件,由于我们使用的是“透明式”,所以Add,Remove都是从Folder类型继承下来的 44 45 SonFolder : Folder 46 47 48 49 50 Console.WriteLine(文件或者文件夹已经增加成功51 52 53 54 55 56 Console.WriteLine(文件或者文件夹已经删除成功57 58 59 打开文件夹--该操作相当于Component类型的Operation方法 60 61 62 Console.WriteLine(已经打开当前文件夹63 64 65 66 Program 67 68 static Main() 69 70 71 Folder myword = new Word(); 72 73 myword.Open();打开文件,处理文件 74 75 myword.Add(new SonFolder());抛出异常 76 myword.Remove(77 78 79 Folder myfolder = SonFolder(); 80 myfolder.Open();打开文件夹 81 82 myfolder.Add(成功增加文件或者文件夹 83 myfolder.Remove(成功删除文件或者文件夹 84 85 Console.Read(); 86 87 88 }
安全式的组合模式的实现 class Folder 该类型少了容器对象管理子对象的方法的定义,换了地方,在树枝构件也就是SonFolder类型 10 11 12 13 14 15 class Word : Folder 这类型现在很干净 17 18 19 20 Console.WriteLine(21 23 24 25 SonFolder类型就是树枝构件,现在由于我们使用的是“安全式”,所以Add,Remove都是从此处开始定义的 26 27 class SonFolder : Folder 这里可以是抽象接口,可以自己根据自己的情况而定 28 31 32 33 NextFolder类型就是树枝构件的实现类 NextFolder : SonFolder 70 这是安全的组合模式 75 76 Folder myfolder = NextFolder(); 77 myfolder.Open();打开文件夹 79 此处要是用增加和删除功能,需要转型的操作,否则不能使用 80 ((SonFolder)myfolder).Add(new NextFolder());81 ((SonFolder)myfolder).Remove(82 83 84 86 }
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |