zoukankan      html  css  js  c++  java
  • 设计模式之Composite(组合)模式

    1、出现原因

    1在面向对象系统中,我们常会遇到一类具有“容器”特征的对象——即它们在充当对象的同时,又是其他对象的容器

    如何将“客户代码与复杂的对象容器结构解耦(将这种组合容器对象设计成树形结构,从而可以对下面所有的容器都可以通过最上层 的根对象 实现 统一 的调用,进而客户端就不在乎 其内部是怎么实现的,耦合 降低了)?让对象容器自己来实现自身的复杂结构,从而使得客户代码就像处理简单对象一样来处理复杂的对象容器?

    2、意图

    将对象组合成树形结构以表示“部分-整体”的层次结构。Composite使得用户对单个对象和组合对象的使用具有一致性。(通过 树根对象的 执行方法,从而调用 他下面的所有的子节点)

    3、结构图

    4、代码演示 

    业务实现:

      1     /// <summary>
      2     /// 抽象的统一 入口
      3     /// </summary>
      4     public abstract class AbsCompany
      5     {
      6         protected string Name { set; get; }
      7 
      8         public AbsCompany(string str)
      9         {
     10             this.Name = str;
     11         }
     12 
     13         public abstract void Add(AbsCompany item);
     14 
     15         public abstract void Remove(AbsCompany item);
     16 
     17         public abstract void Show();
     18 
     19         public abstract void DoDuty();
     20 
     21         //增加子节点的 方式可以 设置 父节点属性
     22         public AbsCompany Father { set; get; }
     23 
     24     }
     25 
     26     /// <summary>
     27     /// 叶子节点1
     28     /// </summary>
     29     public class HRPart : AbsCompany
     30     {
     31         public HRPart(string name)
     32             : base(name)
     33         {
     34         }
     35         //叶子节点不能实现 增删节点操作
     36         public override void Add(AbsCompany item)
     37         {
     38             throw new InvalidOperationException("叶子节点不允许操作");
     39         }
     40 
     41         public override void Remove(AbsCompany item)
     42         {
     43             throw new InvalidOperationException("叶子节点不允许操作");
     44         }
     45 
     46         public override void Show()
     47         {
     48             Console.WriteLine("人力资源部:"+base.Name);
     49         }
     50 
     51         public override void DoDuty()
     52         {
     53             Console.WriteLine(base.Name+":致力于招募人才");
     54         }
     55     }
     56 
     57 
     58     /// <summary>
     59     /// 叶子节点2
     60     /// </summary>
     61     public class MoneyPart : AbsCompany
     62     {
     63         public MoneyPart(string name)
     64             : base(name)
     65         {
     66         }
     67 
     68         //叶子节点不能实现 增删节点的操作
     69         public override void Add(AbsCompany item)
     70         {
     71             throw new InvalidOperationException("叶子节点不允许操作");
     72         }
     73 
     74         public override void Remove(AbsCompany item)
     75         {
     76             throw new InvalidOperationException("叶子节点不允许操作");
     77         }
     78 
     79         public override void Show()
     80         {
     81             Console.WriteLine("财务部分:"+base.Name);
     82         }
     83 
     84         public override void DoDuty()
     85         {
     86             Console.WriteLine(base.Name+":致力于管理好公司的财务");
     87         }
     88     }
     89 
     90     /// <summary>
     91     /// 树形节点(Composite)
     92     /// </summary>
     93     public class Company : AbsCompany
     94     {
     95         public Company(string name)
     96             : base(name)
     97         {
     98         }
     99 
    100         //对应 上级节点是 聚合关系
    101         private List<AbsCompany> items = new List<AbsCompany>();
    102 
    103 
    104         public override void Add(AbsCompany item)
    105         {
    106             items.Add(item);
    107 
    108             //父节点方式:增加子节点
    109             item.Father = this;
    110         }
    111        
    112         public override void Remove(AbsCompany item)
    113         {
    114             items.Remove(item);
    115 
    116             //父节点 方式 :删除子节点:
    117             item.Father = null;//此节点没有父节点了,因此它的父节点下面就没有这个子节点了
    118         }
    119         /// <summary>
    120         /// 实现了加载  次节点下面的所有节点:递归
    121         /// (**)调用的顺序:当 调用到一个子节点,会将他的下面 子节点全都调用完成之后,才调用他的兄弟节点
    122         /// </summary>
    123         /// <param name="item"></param>
    124         public override void Show()
    125         {
    126             //先显示自己
    127             Console.WriteLine("公司名称:"+base.Name);
    128 
    129             //显示下面所有的子节点的 名称
    130             foreach (var item in items)
    131             {
    132                 item.Show();
    133             }
    134 
    135             //注意:要是使用 父节点的方式 实现树形组合:这个时候递归遍历下面所有的子节点的方式就不能执行了
    136         }
    137 
    138         public override void DoDuty()
    139         {
    140             //先执行自己的职责
    141             Console.WriteLine(base.Name+":致力于管理好整个公司");
    142 
    143             //在执行 他的节点下面的所有的节点的 所有的职责
    144             foreach (var item in items)
    145             {
    146                 item.DoDuty();
    147             }
    148 
    149         }
    150     }
    Composite模式

    客户端调用代码:

     1             //都是通过AbsCompany,后面创建的过程 可以通过 反射进行创建。所以客户 就可以直接 通过树形节点的 最顶层节点 就行创建下面一系列的节点,不用关心具体的实现  (耦合 大大降低)
     2             AbsCompany HeadCompany = new Company("阿里巴巴");
     3             AbsCompany hr1 = new HRPart("总公司人力资源部");
     4             AbsCompany money1 = new MoneyPart("总公司财务部");
     5             AbsCompany company1 = new Company("上海分公司");
     6             AbsCompany company2 = new Company("北京办事处");
     7             AbsCompany hr2 = new HRPart("上海分公司人力资源部");
     8             AbsCompany money2 = new MoneyPart("上海分公司财务部");
     9             AbsCompany hr3 = new HRPart("北京人力资源部");
    10             AbsCompany money3 = new MoneyPart("北京财务部门");
    11             AbsCompany company3 = new Company("深圳办事处");
    12             AbsCompany hr4 = new HRPart("深圳人力资源部");
    13             AbsCompany money4 = new MoneyPart("深圳财务部");
    14             HeadCompany.Add(company1);
    15             HeadCompany.Add(hr1);
    16             HeadCompany.Add(money1);
    17             company1.Add(hr2);
    18             company1.Add(money2);
    19             company1.Add(company2);
    20             company1.Add(company3);
    21             company2.Add(hr3);
    22             company2.Add(money3);
    23             company3.Add(hr4);
    24             company3.Add(money4);
    25             HeadCompany.Show();
    26             HeadCompany.DoDuty();
    客户端调用代码

    每个对象的创建可以通过反射的方式进行创建 

    5、实现Composite模式两种方式

    透明方式和安全模式

    7、适用性

    两个或者多个类有相似的形式,或者共同代表某个完整概念,(所有的类都有几乎相同的成员,并且叶子节点可以含有多个)外界的用户也希望他们合而为一(通过一个抽象的基类和接口 就可以 指向所有的类,用户不用关心具体的实现),就可以把这几个类“组合”起来,成为一个新的类,用户只需要调用这个新的类就可以了。

    8、总结

    1Composite模式采用树形结构实现普遍存在的对象容器,从而将“一对多”的关系转化“一对一”的关系,使得客户代码可以一致地处理对象和对象容器,无需关心处理的是单个的对象还是组合的对象容器。(因为这些对象都有几乎相同的结构,所以可以通过抽象基类或接口 进行 调用)

     

    2将“户代码与复杂的对象容器结构解耦(因为所有的类含有 几乎相同的 结构,所以可以通过抽象基类或 接口进行调用,所以用户 只需直接 调用,不许关心 其内部是怎么实现的,耦合大大降低)是Composite模式的核心思想,解耦之后,客户代码将与纯粹的抽象接口——而非对象容器的内部实现结构——发生依赖关系,从而更能“应对变化”。(客户端和抽象接口发生依赖关系)

     

    3Composite模式中,是将“AddRemove等和对象容器相关的方法”定义在“表示抽象对象的Component类”中,还是将其定义在“表示对象容器的Composite类”中,是一个关乎“透明性”和“安全性”的两难问题需要仔细权衡。这里有可能违背面向对象的“单一职责原则”(基于透明性:则违背;基于安全性:则遵守),但是对于这种特殊结构,这又是必须付出的代价。

     

    4、Composite模式在具体实现中,可以让父对象中的子对象反向追溯;如果父对象有频繁的遍历需求,可使用缓存技巧来改善效率。

    5、Composite模式一般都 和 Builder 模式组合起来使用(Builder模式:http://www.cnblogs.com/xiaoxiaogogo/p/3572618.html),每个对象的创建通过Builder模式进行创建(将表示和创建隔离,达到解耦的目的)

  • 相关阅读:
    JDBC
    MySQL 事务
    MySQL 处理海量数据时一些优化查询速度方法
    MySQL 分支和循环结构
    MySQL 分页查询和存储过程
    Oracle PL/SQL异常、存储过程和触发器
    Oracle PL/SQL游标
    mysql主键问题
    spring-springmvc code-based
    AOP实现原理
  • 原文地址:https://www.cnblogs.com/xiaoxiaogogo/p/3590977.html
Copyright © 2011-2022 走看看