一、定义
动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更为灵活。
二、结构图
装饰模式就是利用SetComponent来对对象进行包装的。这样每个装饰对象的实现就和如何使用这个对象分离开了,每个装饰对象只关心自己的功能,不需要关心如何被添加到对象链当中。
三、实例
如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。同样道理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。
如下实例属于上述第一种情况:
Person类(ConcreteComponent)
public class Person
{
public Person( )
{
}
private string name;
public Person( string name )
{
this.name = name;
}
public virtual void Show( )
{
Console.WriteLine( "装扮的{0}", name );
}
}
服饰类(Decorator)
class Finery : Person
{
protected Person component;
//关键点:利用Decorate (SetComponent)来对对象进行包装
public void Decorate( Person component )
{
this.component = component;
}
public override void Show()
{
if( component != null )
{
component.Show( );
}
}
}
具体服饰类(ConcreteDecorator)
class BigTrouser : Finery
{
public override void Show( )
{
Console.Write( "垮裤 " );
base.Show( );
}
}
class Sneaker : Finery
{
public override void Show( )
{
Console.Write( "破球鞋 " );
base.Show( );
}
}
class TShits : Finery
{
public override void Show( )
{
Console.Write( "T-Shit " );
base.Show( );
}
}
调用:
static void Main( string[ ] args )
{
Person andy = new Person( "andy" );
Sneaker sneaker = new Sneaker( );
BigTrouser bigtrouser = new BigTrouser( );
TShits tshit = new TShits( );
sneaker.Decorate( andy );
bigtrouser.Decorate( sneaker );
tshit.Decorate( bigtrouser );
tshit.Show( );
Console.Read( );
}
运行结果:
四、总结
装饰模式是为已有功能动态地添加更多功能的一种方式。
优点:
- 装饰这模式和继承的目的都是扩展对象的功能,但装饰者模式比继承更灵活
- 通过使用不同的具体装饰类以及这些类的排列组合,设计师可以创造出很多不同行为的组合
- 装饰者模式有很好地可扩展性
缺点:
装饰者模式会导致设计中出现许多小对象,如果过度使用,会让程序变的更复杂。并且更多的对象会是的差错变得困难,特别是这些对象看上去都很像。
五、使用场景
下面让我们看看装饰者模式具体在哪些情况下使用,在以下情况下应当使用装饰者模式:
- 需要扩展一个类的功能或给一个类增加附加责任。
- 需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
- 需要增加由一些基本功能的排列组合而产生的非常大量的功能