装饰者模式(Decorator Pattern)
装饰者模式(Decorator Pattern),动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
别名using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyDecorator { abstract class Component { public abstract void Operation(); } class ConcreteComponent : Component { public override void Operation() { Console.WriteLine("ConcreteComponent Operation"); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyDecorator { abstract class Decorator : Component { protected Component component; // 对对象进行包装 // public void SetComponent(Component component) // { // this.component = component; // } public override void Operation() { if (component != null) { component.Operation(); } } } class ConcreteDecoratorA : Decorator { private string addedState; public ConcreteDecoratorA(Component component) { this.component = component; } public override void Operation() { base.Operation(); addedState = "New State"; Console.WriteLine("ConcreteDecoratorA Operation"); } } class ConcreteDecoratorB : Decorator { public ConcreteDecoratorB(Component component) { this.component = component; } public override void Operation() { base.Operation(); AddeeBehavior(); Console.WriteLine("ConcreteDecoratorB Operation"); } private void AddeeBehavior() { } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyDecorator { class Program { static void Main(string[] args) { // ConcreteComponent c = new ConcreteComponent(); // ConcreteDecoratorA da = new ConcreteDecoratorA(); // ConcreteDecoratorB db = new ConcreteDecoratorB(); // // da.SetComponent(c); // db.SetComponent(da); // db.Operation(); ConcreteDecoratorB db = new ConcreteDecoratorB( new ConcreteDecoratorA(new ConcreteComponent())); db.Operation(); Console.ReadKey(); } } }
效果
有效地把类的核心职责和装饰功能区分开了,而且可以去除相关类中重复的装饰逻辑。利用继承设计子类的行为,是在编译时静态决定的,而且所有的子类都会继承到相同的行为。然而,如果能够利用组合的做法扩展对象的行为,就可以在运行时动态地进行扩展。
实现
1)接口的一致性 装饰对象的接口必须与它所装饰的Component的接口是一致的。
2)省略抽象的Decorator类 当你仅需要添加一个职责时,没有必要定义抽象Decorator类。
3)保持Component类的简单性 它应集中于定义接口而不是存储数据。
4)改变对象外壳与改变对象内核(Decorator Pattern VS Strategy Pattern)。
dome
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyDecorator2 { abstract class Beverage { public string description = "Unknown Beverage"; public virtual string getDescription() { return description; } public abstract double cost(); } class Espresso : Beverage { public Espresso() { description = "Espresso"; } public override double cost() { return 1.99; } } class HouseBlend : Beverage { public HouseBlend() { description = "House Blend Coffee"; } public override double cost() { return 0.89; } } class DarRoast : Beverage { public DarRoast() { description = "Dark Roast Coffee"; } public override double cost() { return 0.99; } } class Decaf : Beverage { public Decaf() { description = "Decaf"; } public override double cost() { return 1.05; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyDecorator2 { abstract class CondimentDecorator : Beverage { public override string getDescription() { return description; } } class Mocha : CondimentDecorator { Beverage beverage; // 被装饰者 public Mocha(Beverage beverage) { this.beverage = beverage; } public override string getDescription() { return beverage.getDescription() + ", Mocha"; } public override double cost() { return beverage.cost() + 0.20; } } class Milk : CondimentDecorator { Beverage beverage; // 被装饰者 public Milk(Beverage beverage) { this.beverage = beverage; } public override string getDescription() { return beverage.getDescription() + ", Milk"; } public override double cost() { return beverage.cost() + 0.10; } } class Soy : CondimentDecorator { Beverage beverage; // 被装饰者 public Soy(Beverage beverage) { this.beverage = beverage; } public override string getDescription() { return beverage.getDescription() + ", Soy"; } public override double cost() { return beverage.cost() + 0.15; } } class Whip : CondimentDecorator { Beverage beverage; // 被装饰者 public Whip(Beverage beverage) { this.beverage = beverage; } public override string getDescription() { return beverage.getDescription() + ", Whip"; } public override double cost() { return beverage.cost() + 0.10; } } }
<pre name="code" class="csharp">using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MyDecorator2 { class Program { static void Main(string[] args) { Beverage beverage = new Espresso(); Console.WriteLine(beverage.getDescription() + " $" + beverage.cost()); Beverage beverage2 = new DarRoast(); beverage2 = new Mocha(beverage2); beverage2 = new Mocha(beverage2); beverage2 = new Whip(beverage2); Console.WriteLine(beverage2.getDescription() + " $" + beverage2.cost()); // Beverage beverage3 = new HouseBlend(); // beverage3 = new Soy(beverage3); // beverage3 = new Mocha(beverage3); // beverage3 = new Whip(beverage3); Beverage beverage3 = new Whip(new Mocha(new Soy(new HouseBlend()))); Console.WriteLine(beverage3.getDescription() + " $" + beverage3.cost()); Console.ReadKey(); } } }
相关模式
Adapter模式:Decorator模式不同于Adapter模式,因为装饰仅改变对象的职责而不改变它的接口;而适配器将给对象一个全新的接口。
Composite模式:可以将装饰视为一个退化的、仅有一个组件的组合。然而,装饰仅给对象添加一些额外的职责—它的目的不在于对象聚集。
Strategy模式:用一个装饰你可以改变对象的外表;而Strategy模式使得你可以改变对象的内核。这是改变对象的两种途径。
回顾Strategy Pattern结构
设计原则
类应该对扩展开放,对修改关闭。(遵循开放-关闭原则,通常会引入新的抽象层次,增加代码的复杂度。应该把注意力集中在设计中最有可能改变的地方,然后应用开放-关闭原则。)
java.io类使用了装饰模式。
学一门技能最好的时间是三年前。