组合模式(Composite Pattern)

  • 组合模式概述

定义:组合多个对象造成树形结构以表示具备部分-总体关系的层次结构。组合模式让客户端能够统一对待单个对象和组合对象。又被成为“部分-总体”(Part-Whole)模式,属于对象结构性模式安全

定义什么的,最枯燥了。简单的来讲,就如咱们鼠标右击新建文件夹同样,在一个磁盘里,咱们能够新建一个文件夹A,也能够新建某个类型的文件a,A和a都在同一目录下,固然,咱们也能够点击进入文件夹A,在A中新建新的文件夹B,也能够在A中新建文件b。只要是文件夹,就能够在里面继续新建文件夹和文件,而文件则只能用来放数据,不能在新建了。ide

固然,也能够经过win+r调出运行,输入cmd(commmand),进入你想查看文件的磁盘,输入tree命令,就能够结构性的查看全部文件。在上述图中能够看出文件结构就如同一棵树,有文件夹,有文件,咱们把文件成为叶子(Laef),由于文件不能再展开了,就如树形结构中叶子是最底层了;把文件夹称为容器(Container),由于文件夹里既能够文件夹,又能够放文件。当想要查看一个磁盘的全部文件时,可使用DFS(深度优先搜索)即递归的对每一个文件夹进行一样的搜索,一条路走到底,当访问到叶子结点时,再退回去访问别的结点。this

  • 组合模式结构和实现

  1. Component(抽象构件):它能够是接口或抽象类,为叶子构件和容器构件对象声明接口。定义了访问管理它的子构件的方法,就是对一个子构件该有的操做都应该在这声明,如建立子构件,删除子构件,打开子构件,重命名子构件,复制子构件.......
  2. Leaf(叶子构件):表明一个文件,实如今Component中的行为,即对文件的操做,能够是读文件,写文件,删除文件,复制文件......
  3. Composite(容器构件):表明一个文件夹,它提供一个集合放子节点,能够是文件夹,也能够是文件,因此它有一个聚合箭头指向Component,表明能够递归的建立构件
 1 abstract class Component
 2 {
 3     public abstract void Add(Component c);
 4     public abstract void Remove(Component c);
 5     public abstract Component GetChild(int i);
 6     public abstract void Operation();
 7 }
 8 class Leaf : Component
 9 {
10     public override void Add(Component c)
11     {
12         //throw new NotImplementedException();//这里是报错,叶子文件没有此方法的
13     }
14     
15     public override void Remove(Component c)
16     {
17         //throw new NotImplementedException();//同上
18     }
19     
20     public override Component GetChild(int i )
21     {
22         //throw new NotImplementedException();//同上
23         return null;
24     }
25     
26     public override void Operation()
27     {
28         //对文件的可执行方法
29     }    
30 }
31 class Composite : Component
32 {
33     private IList<Component> list = new List<Component>();//这里通链表容器存放文件夹
34     public override void Add(Component c)
35     {
36         list.Add(c);
37     }
38     
39     public override void Remoce(Component c)
40     {
41         list.Remove(c);
42     }
43     
44     public override Component GetChild(int i )
45     {
46         return (Component)list(c);
47     }
48     
49     public override void Operation()
50     {
51         //递归实现容器中的对文件的方法
52         foreach(Component child in list)
53         {
54             (Component)child.Operation();
55         }
56     }    
57 }
  • 组合模式的应用

 教育机构的OA系统要给各办公室下发公文(IssuedBytheOfficeDoucument),采用组合模式模拟实现spa

分析:从图中能够看出,北京总部,湖南分校,长沙叫教学点,湘潭教学点这几个有子构件,因此它们为文件容器,而教务办公室,行政办公室即为叶子,固然,每一个叶子是不一样的,要区别开。所以咱们定义一个抽象机构类(AbstractInstitutions),其中声明Add,Remove,GetChild和IssuedBytheOfficeDoucument方法3d

1  abstract class AbstractInstitutions//Component
2     {
3         public abstract void Add(AbstractInstitutions institutions);
4         public abstract void Remove(AbstractInstitutions institutions);
5         public abstract AbstractInstitutions GetChild(int i);
6         public abstract void IssuedBytheOfficeDoucument();
7     }
View Code

教务办公室,有本身的名字,即哪个教务办公室,它只能收到下发的公文code

 1  class AcademicAffairsOffice : AbstractInstitutions//Leaf 教务办公室
 2     {
 3         private string name;
 4         public AcademicAffairsOffice(string name)
 5         {
 6             this.name = name;
 7         }
 8         public override void Add(AbstractInstitutions institutions)
 9         {
10             Console.WriteLine("Can't realize this method!!!");
11         }
12 
13         public override void Remove(AbstractInstitutions institutions)
14         {
15             Console.WriteLine("Can't realize this method!!!");
16         }
17 
18         public override AbstractInstitutions GetChild(int i)
19         {
20             Console.WriteLine("Can't realize this method!!!");
21             return null;
22         }
23 
24         public override void IssuedBytheOfficeDoucument()
25         {
26             Console.WriteLine("issued by the office doucument to the {0}",name);
27         }
28     }
View Code

行政办公室和教务办公室相似的实现对象

 1 class AdministrationOffice : AbstractInstitutions//Leaf  行政办公室
 2     {
 3          private string name;
 4         public AdministrationOffice(string name)
 5         {
 6             this.name = name;
 7         }
 8 
 9         public override void Add(AbstractInstitutions institutions)
10         {
11             Console.WriteLine("Can't realize this method!!!");
12         }
13 
14         public override void Remove(AbstractInstitutions institutions)
15         {
16             Console.WriteLine("Can't realize this method!!!");
17         }
18 
19         public override AbstractInstitutions GetChild(int i)
20         {
21             Console.WriteLine("Can't realize this method!!!");
22             return null;
23         }
24 
25         public override void IssuedBytheOfficeDoucument()
26         {
27             Console.WriteLine("issued by the office doucument to the {0}", name);
28         }
29     }
View Code

容器类中实现抽象构件中的方法,而且要向下属机构下发公文blog

 1 class TeachArea : AbstractInstitutions//Composite //教学点
 2     {
 3         private string name;
 4         private IList<AbstractInstitutions> AreaList = new List<AbstractInstitutions>();
 5        
 6         public TeachArea(String name)
 7         {
 8             this.name = name;
 9         }
10 
11         public override void Add(AbstractInstitutions institutions)
12         {
13             AreaList.Add(institutions);
14         }
15 
16         public override void Remove(AbstractInstitutions institutions)
17         {
18             AreaList.Remove(institutions);
19         }
20 
21         public override AbstractInstitutions GetChild(int i)
22         {
23             return (AbstractInstitutions)AreaList[i];
24         }
25 
26         public override void IssuedBytheOfficeDoucument()
27         {
28             Console.WriteLine("Issue official documents to the {0}", name);
29             foreach (Object obj in AreaList)
30             {
31                 ((AbstractInstitutions)obj).IssuedBytheOfficeDoucument();
32             }
33         }
34     }
View Code

Program中,要将全部的机构建立出来,并一一Add到对应的容器中,最后有由北京总部向下发送公文继承

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             AbstractInstitutions BeijingHeadquarters;
 6             BeijingHeadquarters = new TeachArea("BeijingHeadquarters");
 7 
 8             AbstractInstitutions BeijingAcademicAffairsOffice;
 9             BeijingAcademicAffairsOffice = new AcademicAffairsOffice("BeijingAcademicAffairsOffice");
10             AdministrationOffice BeijingAdministrationOffice;
11             BeijingAdministrationOffice = new AdministrationOffice("BeijingAdministrationOffice");
12 
13             AbstractInstitutions HunanPartition;
14             HunanPartition = new TeachArea("HunanPartition");
15 
16             AbstractInstitutions HunanChangshaArea;
17             HunanChangshaArea = new TeachArea("HunanChangshaArea");
18 
19             AbstractInstitutions HunanXiangtanArea;
20             HunanXiangtanArea = new TeachArea("HunanXiangtanArea");
21 
22             AbstractInstitutions HunanAcademicAffairOffice;
23             HunanAcademicAffairOffice = new AcademicAffairsOffice("HunanAcademicAffairOffice");
24             AbstractInstitutions HunanAdministrationOffice;
25             HunanAdministrationOffice = new AdministrationOffice("HunanAdministrationOffice");
26 
27             Console.WriteLine();
28             AbstractInstitutions ChangshaAcademicAffairOffice;
29             ChangshaAcademicAffairOffice = new AcademicAffairsOffice("ChangshaAcademicAffairOffice");
30 
31             AbstractInstitutions ChangshaAdministrationOffice;
32             ChangshaAdministrationOffice = new AdministrationOffice("ChangshaAdministrationOffice");
33             AbstractInstitutions XiangtanAcademicAffairOffice;
34             XiangtanAcademicAffairOffice = new AcademicAffairsOffice("XiangtanAcademicAffairOffice");
35 
36             AbstractInstitutions XiangtanAdministrationOffice;
37             XiangtanAdministrationOffice = new AdministrationOffice("XiangtanAdministrationOffice");
38 
39             HunanChangshaArea.Add(ChangshaAcademicAffairOffice);
40             HunanChangshaArea.Add(ChangshaAdministrationOffice);
41 
42             HunanXiangtanArea.Add(XiangtanAcademicAffairOffice);
43             HunanXiangtanArea.Add(XiangtanAdministrationOffice);
44 
45             HunanPartition.Add(HunanChangshaArea);
46             HunanPartition.Add(HunanXiangtanArea);
47             HunanPartition.Add(HunanAcademicAffairOffice);
48             HunanPartition.Add(HunanAdministrationOffice);
49 
50             BeijingHeadquarters.Add(BeijingAcademicAffairsOffice);
51             BeijingHeadquarters.Add(BeijingAdministrationOffice);
52             BeijingHeadquarters.Add(HunanPartition);
53             BeijingHeadquarters.IssuedBytheOfficeDoucument();
54         }
55     }
View Code

运行结果:递归

  • 透明组合模式和安全组合模式

  • 透明组合模式

Component中声明全部的方法,这样知足了一致性的原则,即对叶子和容器对象都是同样的处理,不需用再去判断,这个对象是叶子仍是容器啊,若是是容器,能够实现哪些方法,若是是叶子,又只能实现哪些方法。这些判断都不须要。可是,因为叶子也继承了Component的方法,所以不安全,叶子对象不能调用Add,Remove,GetChild的方法,若是运行时调用,会出错,所以要提供错误处理代码(如上述例子中的( Console.WriteLine("Can't realize this method!!!");

  • 安全组合模式

Component中没有声明任何方法,而是在Composite中声明并实现,这样作不会由于Leaf调用错误的方法而报错,但缺点是不够透明,即要区别的对待叶子构件和容器构件,可是平常使用是不少的,毕竟安全的每每好不少

上面的例子使用了透明组合模式

  • 组合模式的优缺点和适用环境

  • 组合模式的优势:
  1. 能够清楚的定义分层次的复杂对象,表示对象的所有会部分层次,让客户忽略层次的差别,方便控制
  2. 客户端能够一致性的使用一个组合结构或其中单个对象,没必要关心处理的是单个对象(叶子文件)仍是组合结构(文件夹容器),简化了客户端代码
  3. 增长新的容器构件和叶子构件很方便
  4. 为树型结构的面向对象实现了一种灵活的解决方案
  • 组合模式的缺点:
  1. 在增长新的构件时很难对容器中的构件类型进行控制。若是我但愿文件夹里只能放文件时,则须要复杂的实现过程来实现
  • 组合模式的适用环境
  1. 在具备总体和部分层次的结构中,但愿经过一种方式忽略总体与部分的差别,一致的对待它们
  2. 在一个使用面向对象语言开发的系统中要处理一个树形结构时
  3. 在一个系统总可以分离出叶子和容器对象,并且它们的类型不固定,须要增长一些新的类型
相关文章
相关标签/搜索