装饰者模式(Decorator Pattern)
装饰者模式(Decorator Pattern),动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。
别名包装器Wrapper
结构
参与者
Component
——定义一个对象接口,可以给这些对象动态地添加职责。
ConcreteComponent
——定义一个对象,可以给这个对象添加一些职责。
Decorator
——维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
ConcreteDecorator
——向组件添加职责。
代码
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类使用了装饰模式。
学一门技能最好的时间是三年前。