装饰(Decorator)模式又名包装(Wrapper)模式[GOF95]。装饰模式以对客户端透明的方 式扩展对象的功能,是继承关系的一个替代方案。
装饰模式类图:
类图说明:
抽象构件(Component)角色:给出一个抽象接口,以 规范准备接收附加责任的对象。
具体构件(Concrete Component)角色:定义一个将 要接收附加责任的类。
装饰(Decorator)角色:持有一个构件(Component) 对象的实例,并定义一个与抽象构件接口一致的接口。
具体装饰(Concrete Decorator)角色:负责给构件对 象"贴上"附加的责任
示例代码:
class Program
{
static void Main(string[] args)
{
Component component = new ConcreteComponent();
ConcreteDecoratorA decoratorA = new ConcreteDecoratorA();
ConcreteDecoratorB decoratorB = new ConcreteDecoratorB(); decoratorA.SetComponent(component);
decoratorB.SetComponent(decoratorA); decoratorB.Operation();
Console.ReadKey(); }
} abstract class Component
{
public abstract void Operation();
} class ConcreteComponent : Component
{
public override void Operation()
{
Console.WriteLine("ConcreteComponent.OPeration");
}
} abstract class Decorator : Component
{
protected Component compontent; public void SetComponent(Component compontent)
{
this.compontent = compontent;
} public override void Operation()
{
if (compontent != null)
{
compontent.Operation();
}
}
} class ConcreteDecoratorA : Decorator
{
public override void Operation()
{
base.Operation();
AddedBehavior();
Console.WriteLine("ConcreteDecoratorA.Operation()");
} void AddedBehavior()
{ }
} class ConcreteDecoratorB : Decorator
{ // Methods
override public void Operation()
{
base.Operation();
AddedBehavior();
Console.WriteLine("ConcreteDecoratorB.Operation()");
}
void AddedBehavior() { }
}
运行结果:
在以下情况下应当使用装饰模式:
1. 需要扩展一个类的功能,或给一个类增加附加责任。
2. 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
3. 需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
使用装饰模式主要有以下的优点:
1. 装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。
2. 通过使用不同的具体装饰类以及这些装饰类的排列组合, 设计师可以创造出很多不同行为的组合。
3. 这种比继承更加灵活机动的特性,也同时意味着装饰模式比继承更加易于出错。
使用装饰模式主要有以下的缺点:
由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。
更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。