[Head First设计模式]生活中学设计模式——组合模式
系列文章
[Head First设计模式]山西面馆中的设计模式——装饰者模式
[Head First设计模式]山西面馆中的设计模式——观察者模式
[Head First设计模式]山西面馆中的设计模式——建造者模式
[Head First设计模式]饺子馆(冬至)中的设计模式——工厂模式
[Head First设计模式]抢票中的设计模式——代理模式
[Head First设计模式]云南米线馆中的设计模式——模版方法模式
[Head First设计模式]餐馆中的设计模式——命令模式
[Head First设计模式]身边的设计模式——适配器模式
[Head First设计模式]生活中学设计模式——迭代器模式
引言
比如:复制文件,可以一个一个文件复制粘贴也可以整个文件夹进行复制粘贴。
组合模式
允许你将对象组合成树形结构来表现“整体/部分”层次结构。组合能让客户以一致的方式处理个别对象以及对象组合。
类图
角色
Component:为组合中的对象声明接口。
Leaf:在组合中表示没有子节点的叶节点。
Composite 定义有枝节点行为,用来存储子部件,在Component接口中实现与子部件有关操作,如增加(add)和删除(remove)等。
适用场景
希望把对象表示成整体-部分层次结构。
希望永固忽略组合对象与单个对象的不同,用户将统一使用组合结构中所有对象。
优点
基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去。客户代码中,任何用到基本对象的地方都可以使用组合对象。
客户可以一致的使用组合结构和单个对象。这样用户就不必关心处理的是一个叶节点还是一个组合组件。这样就大大简化了客户代码。
新定义的Componnt或Leaf子类自动地与已有的结构和客户代码一起协同工作,客户程序不需要因新的Component类而改变。
缺点
直接使用了实现类,在面向抽象编程上是很不恰当的,与依赖倒置原则冲突。
一个例子
比如oa系统中最常见的组织结构关系:
1 namespace Wolfy.组合模式 2 { 3 /// <summary> 4 /// 抽象接口类 5 /// </summary> 6 public abstract class Company 7 { 8 public Company(string name) 9 { this.Name = name; } 10 public string Name { get; set; } 11 public abstract void Add(Company company); 12 public abstract void Remove(Company company); 13 public abstract void Display(int depth); 14 } 15 }
1 namespace Wolfy.组合模式 2 { 3 /// <summary> 4 /// 叶节点 子公司 部门类 5 /// </summary> 6 public class ConcreteCompany:Company 7 { 8 private List<Company> list= new List<Company>(); 9 public ConcreteCompany(string name) 10 : base(name) 11 { } 12 public override void Add(Company company) 13 { 14 list.Add(company); 15 } 16 17 public override void Remove(Company company) 18 { 19 list.Remove(company); 20 } 21 22 public override void Display(int depth) 23 { 24 StringBuilder sb = new StringBuilder(); 25 for (int i = 0; i < depth; i++) 26 { 27 sb.Append("-"); 28 } 29 Console.WriteLine(sb.ToString()+base.Name); 30 Console.WriteLine(); 31 foreach (Company item in list) 32 { 33 item.Display(depth + 2); 34 } 35 } 36 } 37 }
1 namespace Wolfy.组合模式 2 { 3 /// <summary> 4 /// 叶节点类 人事部 5 /// </summary> 6 public class HRDepartment:Company 7 { 8 public HRDepartment(string name) 9 : base(name) 10 { } 11 public override void Add(Company company) 12 { 13 throw new NotImplementedException(); 14 } 15 16 public override void Remove(Company company) 17 { 18 throw new NotImplementedException(); 19 } 20 21 public override void Display(int depth) 22 { 23 24 Console.WriteLine(new String('-', depth) + base.Name); 25 26 Console.WriteLine(); 27 } 28 } 29 }
1 namespace Wolfy.组合模式 2 { 3 /// <summary> 4 /// 叶节点 财务部 5 /// </summary> 6 public class FinanceDepartment:Company 7 { 8 public FinanceDepartment(string name) : base(name) { } 9 public override void Add(Company company) 10 { 11 throw new NotImplementedException(); 12 } 13 14 public override void Remove(Company company) 15 { 16 throw new NotImplementedException(); 17 } 18 19 public override void Display(int depth) 20 { 21 Console.WriteLine(new String('-', depth) + base.Name); 22 Console.WriteLine(); 23 } 24 } 25 }
1 namespace Wolfy.组合模式 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Company root = new ConcreteCompany("北京总公司"); 8 root.Add(new HRDepartment("总公司人力资源部")); 9 root.Add(new FinanceDepartment("总公司财务部")); 10 Company shandongCom = new ConcreteCompany("山东分公司"); 11 shandongCom.Add(new HRDepartment("山东分公司人力资源部")); 12 shandongCom.Add(new FinanceDepartment("山东分公司账务部")); 13 Company zaozhuangCom = new ConcreteCompany("枣庄办事处"); 14 zaozhuangCom.Add(new FinanceDepartment("枣庄办事处财务部")); 15 zaozhuangCom.Add(new HRDepartment("枣庄办事处人力资源部")); 16 Company jinanCom = new ConcreteCompany("济南办事处"); 17 jinanCom.Add(new FinanceDepartment("济南办事处财务部")); 18 jinanCom.Add(new HRDepartment("济南办事处人力资源部")); 19 shandongCom.Add(jinanCom); 20 shandongCom.Add(zaozhuangCom); 21 Company huadongCom = new ConcreteCompany("上海华东分公司"); 22 huadongCom.Add(new HRDepartment("上海华东分公司人力资源部")); 23 huadongCom.Add(new FinanceDepartment("上海华东分公司账务部")); 24 Company hangzhouCom = new ConcreteCompany("杭州办事处"); 25 hangzhouCom.Add(new FinanceDepartment("杭州办事处财务部")); 26 hangzhouCom.Add(new HRDepartment("杭州办事处人力资源部")); 27 Company nanjingCom = new ConcreteCompany("南京办事处"); 28 nanjingCom.Add(new FinanceDepartment("南京办事处财务部")); 29 nanjingCom.Add(new HRDepartment("南京办事处人力资源部")); 30 huadongCom.Add(hangzhouCom); 31 huadongCom.Add(nanjingCom); 32 root.Add(shandongCom); 33 root.Add(zaozhuangCom); 34 root.Add(jinanCom); 35 root.Add(huadongCom); 36 root.Add(hangzhouCom); 37 root.Add(nanjingCom); 38 root.Display(0); 39 Console.Read(); 40 } 41 } 42 }
结果:
总结
优点
基本对象可以被组合成更复杂的组合对象,而这个组合对象又可以被组合,这样不断地递归下去。客户代码中,任何用到基本对象的地方都可以使用组合对象。
客户可以一致的使用组合结构和单个对象。这样用户就不必关心处理的是一个叶节点还是一个组合组件。这样就大大简化了客户代码。
新定义的Componnt或Leaf子类自动地与已有的结构和客户代码一起协同工作,客户程序不需要因新的Component类而改变。
缺点
直接使用了实现类,在面向抽象编程上是很不恰当的,与依赖倒置原则冲突。
参考:
《Head First 设计模式》
百度百科