装饰模式(Decorator Pattern) 提供了一个动态增加一个类功能的方法,主要实现思想是通过一个作为装饰者的类(Decorators)包裹被装饰类(Component)(装饰类以及被装饰类都有共同的基类),Decorators 会在 Component 类的某一个函数执行前或后进行一些操作,进而达到增加功能的作用。
装饰模式主要实现了“代码应该对扩展功能开放而对于修改关闭”的面向对象原则,它在增加新功能的前提下,不需要改动既有的代码,只需要增加新的 Decorators 并且包含既有的 Component 即可。
例如我们要计算一杯咖啡的价格,而这杯咖啡的价格还会受到额外的配料的影响,比如要加抹茶需要额外支付 0.2 元,加奶泡需要额外支付 0.3 元等。如果对各种配料都各自使用一个类来表示,则会存在较多的类需要维护,而且一旦配料发生变化等,还需要进行代码修改。而使用装饰模式则可以将原始的咖啡作为被装饰类,而所有的配料都是装饰类,则配料的更改仅需要增加或删除外部的装饰类即可。
代码示例
装饰类及被装饰类基类
被装饰类基类1 2 3 4 5 6 7 8 9 10 11
   | public abstract class Beverage {     protected string description = "UnKnown Beverage";
      public virtual string getDescription()     {         return description;     }
      public abstract double Cost(); }
   | 
 装饰类基类1 2 3 4 5 6 7 8 9
   | public abstract class CondimentDecorator : Beverage {     protected Beverage beverage;
      public CondimentDecorator(Beverage beverage)     {         this.beverage = beverage;     } }
   | 
 注意装饰类基类继承自被装饰类,并存有一个被装饰类的变量,因为装饰类需要在被装饰类操作的基础上进行一定额外的操作,所以它需要存有对被装饰类的引用,同时对外部而言调用者而言,它与被装饰类相同。
被装饰类实现
浓咖啡1 2 3 4 5 6 7 8 9 10 11 12
   | public class Espresso : Beverage {     public Espresso()     {         description = "Espresson";     }
      public override double Cost()     {         return 1.99;     } }
   | 
 装饰类实现
酱油1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | public class Soy : CondimentDecorator {     public Soy(Beverage beverage) : base(beverage) { }
      public override string getDescription()     {         return beverage.getDescription() + ", Soy";     }
      public override double Cost()     {         return 0.30 + beverage.Cost();     } }
   | 
 奶泡1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | public class Whip : CondimentDecorator {     public Whip(Beverage beverage) : base(beverage) { }
      public override string getDescription()     {         return beverage.getDescription() + ", Whip";     }
      public override double Cost()     {         return 0.30 + beverage.Cost();     } }
   | 
 抹茶1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | public class Mocha : CondimentDecorator {     public Mocha(Beverage beverage) : base(beverage) { }
      public override string getDescription()     {         return beverage.getDescription() + ", Mocha";     }
      public override double Cost()     {         return 0.20 + beverage.Cost();     } }
   | 
 测试及结果
测试代码1 2 3 4 5
   | Espresso espresso = new Espresso(); Console.WriteLine(espresso.getDescription() + " Cost: " + espresso.Cost());
  Beverage doubleMochaWhipEspresso = new Mocha(new Mocha(new Whip(espresso))); Console.WriteLine(doubleMochaWhipEspresso.getDescription() + " Cost: " + doubleMochaWhipEspresso.Cost());
   | 
 运行结果:
