装饰者模式(Decorator):定义:在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。
首相了解什么时候会用到 装饰者模式?
当我们在给一个类或对象 增加额外的 功能时, 通常想到的是 直接改变 类,添加功能,这显然违背了 开闭原则,是不可取的,可能会影响到其他正常功能的使用。
还有一种 就是使用继承。 继承 不但 可以 得到 父类的 方法 ,而且 还可以构建自己 需要的方法。 但这种 方法是静态的特质(所谓静态特质,就是说如果想要某种功能,我们必须在编译的时候就要定义这个类,这也是强类型语言的特点。静态,就是指在编译的时候要确定的东西;动态,是指运行时确定的东西),扩展方式十分不灵活,同时,随着需求改变的增多,继承的层次也 越来越多,各种类 造成了 类的膨胀。这时可以使用 同样的 另一种方式:对象组合
使用场合:
- 在不影响其他对象的情况下,以动态的,透明的方式给单个对象添加职责;
- 处理那些可以撤销的职责;
- 当不能采用生成子类的方法进行扩充时。一种情况是,可能存在大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏,或类定义不能用于生成子类。
在装饰模式中的各个角色有:
(1)抽象构件(Component)角色:给出一个抽象接口,以规范准备接收附加责任的对象。
(2)具体构件(Concrete Component)角色:定义一个将要接收附加责任的类。
(3)装饰(Decorator)角色:持有一个构件(Component)对象的实例,并实现一个与抽象构件接口一致的接口。
(4)具体装饰(Concrete Decorator)角色:负责给构件对象添加上附加
下面通过一个小例子来说明一下, 饭店宴席 是 吸引顾客 的特色之一 , 但是 一桌 美味的 宴席 不能是 不变的 , 为了 吸引 大量的 顾客 需要 动态的 去 调整 宴席 的
组合方式, 以 一桌 宴席 包括 鸡,鸭,鱼,鹅,肉,青菜 为准

/// <summary> /// Component 是一个对象接口,可以动态的给这些对象添加职责 /// Component 是被装饰对象的基类 /// </summary> public abstract class Component { public abstract void AddFood(); }

/// <summary> /// 定义 准备接受职责 的类 /// Concretecomponent 是具体被装饰的对象 /// </summary> public class Concretecomponent :Component { public override void AddFood() { } }

/// <summary> /// 装饰抽象类 继承 Component ,从外部 扩展 Component 的功能 /// Decorator 是装饰者抽象类 /// </summary> public abstract class Decorator : Component { protected Component Component; /// <summary> /// 设置Component 利用 Setcomponent 来对 对对象进行包装,这样每个装饰对象的实现 就和如何 使用这个对象 分离开了 /// 每个装饰对象只关心自己的 功能 不需要关心如何被添加到对象之中(我只关心自己的菜,不关心要怎么上) /// /// </summary> /// <param name="Component"></param> /// Setcomponent 布置餐桌 public void Setcomponent(Component Component) { this.Component = Component; } public override void AddFood() { if (Component != null) { //重写 Operation ,实际执行的 是 Component 的 Operation Component.AddFood(); } } }

/// <summary> /// ConcreteDecoratoe 是 具体装饰类 /// </summary> public class ConcreteDecoratoeChicen:Decorator { public override void AddFood() { /// 首先先执行原Component AddFood 的方法,然后再 执行本类中 AddFood 的方法 base.AddFood(); AddChicenfood(); } /// <summary> /// 本类独有的方法,设置自己想要 的流程 /// </summary> private void AddChicenfood() { Console.WriteLine("上一道美味的小鸡炖蘑菇"); } } public class ConcreteDecoratoeDuck : Decorator { public override void AddFood() { /// 首先先执行原Component AddFood 的方法,然后再 执行本类中 AddFood 的方法 base.AddFood(); AddDuckfood(); } /// <summary> /// 本类独有的方法,设置自己想要 的流程 /// </summary> private void AddDuckfood() { Console.WriteLine("来一道北京烤鸭"); } } public class ConcreteDecoratoeFish : Decorator { public override void AddFood() { /// 首先先执行原Component AddFood 的方法,然后再 执行本类中 AddFood 的方法 base.AddFood(); AddFishfood(); } /// <summary> /// 本类独有的方法,设置自己想要 的流程 /// </summary> private void AddFishfood() { Console.WriteLine("上一道美味的深海大鲟鱼"); } } public class ConcreteDecoratoeGoosey : Decorator { public override void AddFood() { /// 首先先执行原Component AddFood 的方法,然后再 执行本类中 AddFood 的方法 base.AddFood(); AddGooseyfood(); } /// <summary> /// 本类独有的方法,设置自己想要 的流程 /// </summary> private void AddGooseyfood() { Console.WriteLine("上一道酱香鹅"); } } public class ConcreteDecoratoeMeat : Decorator { public override void AddFood() { /// 首先先执行原Component AddFood 的方法,然后再 执行本类中 AddFood 的方法 base.AddFood(); AddMeatfood(); } /// <summary> /// 本类独有的方法,设置自己想要 的流程 /// </summary> private void AddMeatfood() { Console.WriteLine("上一道红烧肉"); } } public class ConcreteDecoratoeVegetable : Decorator { public override void AddFood() { /// 首先先执行原Component AddFood 的方法,然后再 执行本类中 AddFood 的方法 base.AddFood(); AddVegetablefood(); } /// <summary> /// 本类独有的方法,设置自己想要 的流程 /// </summary> private void AddVegetablefood() { Console.WriteLine("上一道小青菜"); } }
调用:

Concretecomponent FoodTable = new Concretecomponent(); ConcreteDecoratoeChicen chicen = new ConcreteDecoratoeChicen(); ConcreteDecoratoeGoosey goosey = new ConcreteDecoratoeGoosey(); ConcreteDecoratoeMeat meat = new ConcreteDecoratoeMeat(); ConcreteDecoratoeVegetable vegetable = new ConcreteDecoratoeVegetable(); ConcreteDecoratoeFish fish = new ConcreteDecoratoeFish(); ConcreteDecoratoeDuck duck = new ConcreteDecoratoeDuck(); Console.WriteLine("开始上菜: "); vegetable.Setcomponent(FoodTable); Console.WriteLine(" "); goosey.Setcomponent(vegetable); Console.WriteLine(" "); chicen.Setcomponent(goosey); Console.WriteLine(" "); fish.Setcomponent(chicen); Console.WriteLine(" "); duck.Setcomponent(fish); Console.WriteLine(" "); meat.Setcomponent(duck); Console.WriteLine(" "); meat.AddFood(); Console.Read();
优点
1. Decorator模式与继承关系的目的都是要扩展对象的功能,但是Decorator可以提供比继承更多的灵活性。
2. 通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。
缺点
1. 这种比继承更加灵活机动的特性,也同时意味着更加多的复杂性。
2. 装饰模式会导致设计中出现许多小类,如果过度使用,会使程序变得很复杂。
3. 装饰模式是针对抽象组件(Component)类型编程。但是,如果你要针对具体组件编程时,就应该重新思考你的应用架构,以及装饰者是否合适。当然也可以改变Component接口,增加新的公开的行为,实现“半透明”的装饰者模式。在实际项目中要做出最佳选择。
个人感觉装饰者 模式 更像 大树 主干 和 分支的关系 。