装饰器模式
本片博客将介绍装饰器模式,装饰器模式是一种用于替代继承的技术,它通过一种无需定义子类的方式给对象动态的添加职责,使用对象之间的关联关系替代继承关系。装饰器模式降低了系统的耦合度,可以动态增加或者删除对象的职责,并使得需要装饰的具体构件类和用于装饰的具体装饰类可以相互独立的变化。
模式分类
结构型设计模式。
模式产生的原因
在软件开发时,有些时候我们不能使用继承对系统进行扩展,比如我们想要拓展的类是一个密封类。或者使用继承不利于系统的拓展和维护,比如系统中存在大量独立拓展,为支持每一种拓展或者拓展之间的组合将产生大量的子类,不利于系统维护。这时我们就可以使用装饰器模式,通过关联关系来代替继承关系,从而实现上述问题的解决。
模式的灵感来源
对新房进行装修并没有改变房屋用于居住的本质,但它可以让房子变得更加漂亮,更加温馨,更加实用,更能满足居家的需求。装饰器模式就是这样一种可以在不改变一个对象本身功能的基础上给对象增加额外的新行为,在现实生活中,这种情况也到处存在。例如一张照片,用户可以不改变照片本身,给它增加一个相框,使他具有防潮的功能,还可以根据需要给它增加不同类型的相框,甚至可以在一个小相框上再套一个大相框。
模式类图
装饰器模式包括以下4个角色:
Component(抽象构件):
他是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一制的方式处理未被装饰的对象和装饰后的对象。
ConcreteComponent(具体构件):
它是抽象类的子类,用于定义具体的构件对象,实现抽象类中的方法。
Decorator(抽象装饰类):
也是抽象构件的子类,同时其自身又是装饰类的抽象类,具体的装饰功能将由子类实现。
ConcreteDecorator(具体装饰类):
装饰类的具体实现类,实现抽象类中的方法。
代码实现
经典代码实现:
Component抽象构件:
namespace Decorator.Decorator.Example
{
public abstract class Component
{
public abstract void Operation();
}
}
ConcreteComponent具体构件:
using System;
namespace Decorator.Decorator.Example
{
public class ConcreteComponent : Component
{
public override void Operation()
{
Console.WriteLine($"待装饰基类");
}
}
}
Decorator抽象装饰类:
namespace Decorator.Decorator.Example
{
public class ComponentDecorator : Component
{
private Component _baseComponent;
public ComponentDecorator(Component component)
{
_baseComponent = component;
}
public override void Operation()
{
_baseComponent.Operation();
}
}
}
ConcreteDecorator具体装饰类:
namespace Decorator.Decorator.Example
{
public class ConcreteDecorator : ComponentDecorator
{
public ConcreteDecorator(Component component) : base(component)
{
}
public override void Operation()
{
NewOperation();
base.Operation();
}
private void NewOperation()
{
}
}
}
装饰器模式总结
装饰器模式的优点:
- 对于拓展一个对象的功能,装饰器模式比继承更加灵活,不会导致类的个数极具增加。
- 抽象模式可以通过一种动态的方式来拓展一个对象的功能,通过配置文件在运行时选择不同的具体装饰类从而实现不同的功能。
- 装饰器模式可以对一个对象进行多次装饰,通过不同的具体装饰类的排列组合,我们可以得到更加强大的对象。
- 装饰器模式中,装饰构件和装饰器可以独立的变化。
装饰器模式的缺点:
- 使用装饰器模式会产生很多小细粒度的对象。
- 装饰器模式更加容易出错,对于多次装饰的对象,我们需要逐级排查每个装饰器,比较繁琐。