zoukankan      html  css  js  c++  java
  • 组合模式(Composite Pattern)

    • 组合模式概述

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

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

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

    • 组合模式结构和实现

    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),采用组合模式模拟实现

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

    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

    教务办公室,有自己的名字,即哪一个教务办公室,它只能收到下发的公文

     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

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

     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. 在一个系统总能够分离出叶子和容器对象,而且它们的类型不固定,需要增加一些新的类型
  • 相关阅读:
    SQL Server 触发器
    T-SQL查询进阶-10分钟理解游标
    有关T-SQL的10个好习惯
    iOS 画虚线以及drawRect的使用总结:
    iOS一个for循环实现,几行 几列 的布局形式
    IOS 符合某类型的子视图批量从父视图中移除
    DESC 和 ASC
    把数组格式数据转换成字符串存入数据库
    Swift :?和 !
    Swift 类构造器的使用
  • 原文地址:https://www.cnblogs.com/ygsworld/p/10803240.html
Copyright © 2011-2022 走看看