组合模式

2019-04-14 19:52发布

一、组合模式简介(Brief Introduction)

组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。  

二、解决的问题(What To Solve

解决整合与部分可以被一致对待问题。

三、组合模式分析(Analysis

1、组合模式结构

Component类:组合中的对象声明接口,在适当情况下,实现所有类共有接口的行为。声明一个接口用于访问和管理Component的子部件 Leaf类:叶节点对象,叶节点没有子节点。由于叶节点不能增加分支和树叶,所以叶节点的Add和Remove没有实际意义。 有叶节点行为,用来存储叶节点集合 Composite类:实现Componet的相关操作,比如Add和Remove操作。 children:用来存储叶节点集合

2、源代码

1、抽象类Component public abstract class Component {     protected string name;       public Component(string name)     {         this.name = name;     }       public abstract void Add(Component c);     public abstract void Remove(Component c);     public abstract void Diaplay(int depth); }   2、叶子节点Leaf 继承于Component public class Leaf:Component {       public Leaf(string name)         :base(name)     {             }       public override void Add(Component c)     {         Console.WriteLine("不能向叶子节点添加子节点");     }       public override void Remove(Component c)     {         Console.WriteLine("叶子节点没有子节点");     }       public override void Diaplay(int depth)     {         Console.WriteLine(new string('-',depth)+name);     } }   3、组合类Composite继承于Component,拥有枝节点行为 public class Composite : Component {       List children;       public Composite(string name)         :base(name)     {         if (children == null)         {             children = new List();         }     }       public override void Add(Component c)     {         this.children.Add(c);     }       public override void Remove(Component c)     {         this.children.Remove(c);     }       public override void Diaplay(int depth)     {         Console.WriteLine(new String('-',depth)+name);         foreach (Component component in children)         {             component.Diaplay(depth + 2);         }     } }     4、客户端代码 static void Main(string[] args) {     Composite root = new Composite("根节点root");     root.Add(new Leaf("根上生出的叶子A"));     root.Add(new Leaf("根上生出的叶子B"));       Composite comp = new Composite("根上生出的分支CompositeX");     comp.Add(new Leaf("分支CompositeX生出的叶子LeafXA"));     comp.Add(new Leaf("分支CompositeX生出的叶子LeafXB"));       root.Add(comp);       Composite comp2 = new Composite("分支CompositeX生出的分支CompositeXY");     comp2.Add(new Leaf("分支CompositeXY生出叶子LeafXYA"));     comp2.Add(new Leaf("分支CompositeXY生出叶子LeafXYB"));       comp.Add(comp2);       root.Add(new Leaf("根节点生成的叶子LeafC"));     Leaf leafD = new Leaf("leaf D");     root.Add(leafD);     root.Remove(leafD);     root.Diaplay(1);     Console.Read(); }  

3、程序运行结果

四.案例分析(Example

1、场景

假设公司组织结构为: --总结理 ----技术部门经理 ------开发人员A ------开发人员B ----销售部门经理 总经理直接领导技术部经理和销售部经理,技术部经理直接领导开发人员A和开发人员B。销售部经理暂时没有直接下属员工,随着公司规模增大,销售部门会新增销售员工。计算组织结构的总工资状况。 如下图所示

IComponent接口:此接口包括了Component和Composite的所有属性,公司每个角 {MOD}都有职称Title和工资待遇Salary,Add方法把员工加入到组织团队中。 Component叶子节点:叶节点没有子节点,Add方法实现没有任何意义。 Composite组合类:此类有一个员工集合_listEmployees,Add方法向此集合中添加员工信息。 GetCost方法获得组织结构中的工资待遇总和

2、代码

1、接口IComponent
  1. public interface IComponent   
  2.     {   
  3.         string Title { getset; }   
  4.         decimal Salary { getset; }   
  5.         void Add(IComponent c);   
  6.         void GetCost(ref decimal salary);   
  7.     }   
8.       2、叶节点Component 
  1. public class Component : IComponent   
  2.     {   
  3.         public string Title { getset; }   
  4.         public decimal Salary { getset; }   
  5.   
  6.         public Component(string Title, decimal Salary)   
  7.         {   
  8.             this.Title = Title;   
  9.             this.Salary = Salary;   
  10.         }   
  11.   
  12.         public void Add(IComponent c)   
  13.         {   
  14.             Console.WriteLine("Cannot add to the leaf!");   
  15.         }   
  16.   
  17.         public void GetCost(ref decimal salary)   
  18.         {   
  19.             salary += Salary;   
  20.         }   
  21.     }   
22.         3、组合类Composite  1.   public class Composite : IComponent    2.       {    3.           private List _listEmployees;    4.      5.           public string Title { getset; }    6.           public decimal Salary { getset; }    7.      8.           public Composite(string Title, decimal Salary)    9.           {    10.               this.Title = Title;    11.               this.Salary = Salary;    12.               _listEmployees = new List();    13.           }    14.      15.           public void Add(IComponent comp)    16.           {    17.               _listEmployees.Add(comp);    18.           }    19.      20.           public void GetCost(ref decimal salary)    21.           {    22.               salary += this.Salary;    23.      24.               foreach (IComponent component in this._listEmployees)    25.               {    26.                   component.GetCost(ref salary);    27.               }    28.           }    29.       }        4、客户端代码
  1. static void Main(string[] args)   
  2.         {   
  3.             decimal costCEO = 0.0M;   
  4.             decimal costVPD = 0.0M;   
  5.   
  6.             //Create CEO Node   
  7.             IComponent compCEO = new Composite("CEO", 500000);   
  8.   
  9.             //Create VP-Development and Developer nodes   
  10.             IComponent compVPDev = new Composite("VP-Development", 250000);   
  11.   
  12.             IComponent compDev1 = new Component("Developer1", 75000);   
  13.             IComponent compDev2 = new Component("Developer2", 50000);   
  14.   
  15.             compVPDev.Add(compDev1);   
  16.             compVPDev.Add(compDev2);   
  17.   
  18.             //Create VP-Sales node   
  19.             IComponent compVPSales = new Component("VP-Sales", 300000);   
  20.   
  21.             compCEO.Add(compVPDev);   
  22.             compCEO.Add(compVPSales);   
  23.   
  24.             //Get the cost incurred at the CEO level   
  25.             compCEO.GetCost(ref costCEO);   
  26.   
  27.             Console.WriteLine(String.Format("The Cost incurred at the CEO            level is {0:c} ", costCEO));   
  28.   
  29.             //Get the cost incurred at the VP-Development level   
  30.             compVPDev.GetCost(ref costVPD);   
  31.             Console.WriteLine(String.Format("The Cost incurred at the VP-Development level is {0:c} ", costVPD));   
  32.         }   
33.      

五、总结(Summary

组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。解决整合与部分可以被一致对待问题