有时候需要对某些对象的功能进行扩展,但由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性,并且随着子类增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀,如何使“”对象功能的扩展“”能够根据需要来动态的实现,同时避免“”扩展功能的增多“”带来的子类膨胀问题,从而使得任何“”功能扩展变化“”所导致的影响降为最低?装饰者模式就可适用此需求。
一、装饰模式的意图:
动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。--[GOF 《设计模式》]
二、类图:
在装饰模式中包含以下角色:
● Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
● ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
● Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
● ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
由于具体构件类和装饰类都实现了相同的抽象构件接口,因此装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。
装饰模式的核心在于抽象装饰类的设计:
class Decorator:Component
{
private Component component; //维持一个对抽象构件对象的引用
public Decorator(Component component) //注入一个抽象构件类型的对象
{
this.component=component;
}
public void operation()
{
component.operation(); //调用原有业务方法
}
}
在抽象装饰类Decorator中定义了一个Component类型的对象component,维持一个对抽象构件对象的引用,并可以通过构造方法或Setter方法将一个Component类型的对象注入进来,同时由于Decorator类实现了抽象构件Component接口,因此需要实现在其中声明的业务方法operation(),需要注意的是在Decorator中并未真正实现operation()方法,而只是调用原有component对象的operation()方法,它没有真正实施装饰,而是提供一个统一的接口,将具体装饰过程交给子类完成。
在Decorator的子类即具体装饰类中将继承operation()方法并根据需要进行扩展,典型的具体装饰类代码如下:
class ConcreteDecorator extends Decorator
{
public ConcreteDecorator(Component component)
{
super(component);
}
public void operation()
{
super.operation(); //调用原有业务方法
addedBehavior(); //调用新增业务方法
}
//新增业务方法
public void addedBehavior()
{
……
}
}
在具体装饰类中可以调用到抽象装饰类的operation()方法,同时可以定义新的业务方法,如addedBehavior()。
由于在抽象装饰类Decorator中注入的是Component类型的对象,因此我们可以将一个具体构件对象注入其中,再通过具体装饰类来进行装饰;此外,我们还可以将一个已经装饰过的Decorator子类的对象再注入其中进行多次装饰,从而对原有功能的多次扩展。
四、完整示例:
/// <summary>
/// 抽象构件
/// </summary>
public abstract class Component
{
/// <summary>
/// 抽象构件的业务方法
/// </summary>
public abstract void Operation();
}
public class ConcreteComponent : Component
{
/// <summary>
/// 具体构件的业务方法
/// </summary>
public override void Operation()
{
//...
Console.WriteLine("Concrete component method");
}
}
/// <summary>
/// 抽象装饰类
/// </summary>
public abstract class Decorator : Component
{
private Component component;//维持一个对抽象构件对象的引用
/// <summary>
/// 注入一个实现了抽象构件类型的具体构件的对象
/// </summary>
/// <param name="component"></param>
public Decorator(Component component)
{
this.component = component;
}
/// <summary>
/// 重写抽象构件的业务方法,实现具体构件自己的业务方法(提供一个统一的接口,将具体装饰过程交给具体的构件对象完成。)
/// </summary>
public override void Operation()
{
component.Operation();//调用具体构件的业务方法
}
}
public class ConcreteDecorator : Decorator
{
public ConcreteDecorator(Component component) : base(component)
{
}
public override void Operation()
{
base.Operation();//调用原有业务方法
AddBehavior();//扩展新的业务方法
}
private void AddBehavior()
{
//.....
Console.WriteLine("extend business method1");
}
}
public class ConcreteDecorator2 : Decorator
{
public ConcreteDecorator2(Component component) : base(component)
{
}
public override void Operation()
{
base.Operation();
AddBehavior();
}
private void AddBehavior()
{
Console.WriteLine("extend business method2");
}
}
static void Main(string[] args)
{
Component component = new ConcreteComponent();//具体构件对象
//Decorator decorator = new ConcreteDecorator(component); 或
Component decorator = new ConcreteDecorator(component);//对具体构件进行装饰,装饰后还是一个具体构件(因为Decorator继承了component)
//decorator.Operation();//调用具体构件的业务方法
Component decorator2 = new ConcreteDecorator2(decorator);//还可以将一个已经装饰过的构件多次进行装饰,从而实现对原有功能的多次扩展
decorator2.Operation();
Console.ReadKey();
}