设计模式—组合模式
前言
开发中经常会遇到处理简单对象和复合对象的情况,例如对操作系统中目录的处理,目录可以包含单个的文件,也可以包括文件夹,文件夹又是有文件组成的,由于简单对象和复合对象在功能上区别导致在操作过程中必须区分简单对象和复合对象,这样就会导致客户端带来不必要的麻烦,而作为客户,他们希望能够始终一致的对待简单对象和复合对象。组合模式可以解决这一问题
组合模式介绍
组合模式允许你将对象组合成树形结构来表现‘部分-整体‘的层次结构,使用户以一致的方式处理单个对象以及对象的组合。
组合模式实现的关键是:简单对象和复合对象必须实现相同的接口。这就是组合模式能够将简单对象和复合对象进行一致处理的原因
1)实际例子
生活中店铺的情况有总店和分店,还有加盟店。在使用积分卡时,在总店或分店的积分卡,在加盟店中使用时添加的积分会自动汇总到一起
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleApplication1 7 { 8 /// <summary> 9 /// 店面类 抽象出来的店面部件 10 /// </summary> 11 public abstract class Storefront 12 { 13 //店名 14 protected string storeName = string.Empty; 15 public string StoreName 16 { 17 get 18 { 19 return storeName; 20 } 21 } 22 23 //添加店面 24 public abstract void Add(Storefront store); 25 //删除店面 26 public abstract void Remove(Storefront store); 27 28 //定义所有部件公用的行为 刷卡行为 29 public abstract void PayByCard(); 30 } 31 32 //总店或分店 33 public class StoreOrBranch : Storefront 34 { 35 //构造函数 36 public StoreOrBranch() { } 37 public StoreOrBranch(string storeName) 38 { 39 this.storeName = storeName; 40 } 41 List<Storefront> myStoreList = new List<Storefront>(); 42 //刷卡消费 43 public override void PayByCard() 44 { 45 Console.WriteLine("店面{0}的积分已累加进该会员卡", storeName); 46 foreach (Storefront sf in myStoreList) 47 { 48 sf.PayByCard(); 49 } 50 } 51 52 //增加店面 53 public override void Add(Storefront store) 54 { 55 myStoreList.Add(store); 56 } 57 58 //解除店面 59 public override void Remove(Storefront store) 60 { 61 myStoreList.Remove(store); 62 } 63 } 64 65 //加盟店 66 public class JoinInStore : Storefront 67 { 68 //构造函数 69 public JoinInStore() { } 70 public JoinInStore(string storeName) 71 { 72 this.storeName = storeName; 73 } 74 //刷卡消费 75 public override void PayByCard() 76 { 77 Console.WriteLine("加盟店面{0}的积分已累加进该会员卡", storeName); 78 } 79 80 public override void Add(Storefront store) 81 { 82 throw new NotImplementedException(); 83 } 84 85 public override void Remove(Storefront store) 86 { 87 throw new NotImplementedException(); 88 } 89 } 90 }
调用方法:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleApplication1 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 StoreOrBranch store = new StoreOrBranch("朝阳总店"); 13 StoreOrBranch brach = new StoreOrBranch("东城分店"); 14 JoinInStore jstore = new JoinInStore("海淀加盟店一"); 15 JoinInStore jstore1 = new JoinInStore("上地加盟店二"); 16 17 brach.Add(jstore); 18 brach.Add(jstore1); 19 store.Add(brach); 20 21 store.PayByCard(); 22 } 23 } 24 }
运行结果:
2)组合模式介绍
上面的代码方式称为透明式的组合模式
在加盟店中添加和移除方法是没有使用到的,因此可以换种方式使代码更安全,称为安全式组合模式
组合模式涉及到三个角色
抽象构件角色(Component):这是一个抽象角色,它给参与组合的对象定义了公共的接口及默认行为,可以用来管理所要的子对象(透明模式中是这样)。在安全模式中,构件角色并不定义出管理子对象的方法,这一定义有树枝结构对象给出
树叶构件角色(Leaf):树叶对象是没有下级子对象的对象,定义出参与组合对象的原始对象的行为
树枝构件角色(Composite):代表参与组合的有下级子对象的对象管理,树枝对象给出所以管理子对象的方法实现,如add,remove
3)组合模式分析
优点:
- 组合模式使得客户端代码可以一致地处理对象和对象容器,无需关系处理的单个对象,还是组合的对象容器。
- 将”客户代码与复杂的对象容器结构“解耦。
- 可以更容易地往组合对象中加入新的构件。
缺点:
使得设计更加复杂。客户端需要花更多时间理清类之间的层次关系。
4)组合模式使用场景
- 需要表示一个对象整体或部分的层次结构。
- 希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象。