设计模式(Design pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问,设计模式于己于他人于系统都是多赢的;设计模式使代码编制真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
设计模式分为三种类型,共23种。
创建型模式(5):单例模式、抽象工厂模式、建造者模式、工厂模式、原型模式。
结构型模式(7):适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模式。
行为型模式(11):(父子类)策略模式、模版方法模式,(两个类)观察者模式、迭代器模式、职责链模式、命令模式,(类的状态)状态模式、备忘录模式,(中间类) 访问者模式、中介者模式、解释器模式。
尽管目前房价依旧很高,但还是阻止不了大家对新房的渴望和买房的热情。如果大家买的是毛坯房,无疑还有一项艰巨的任务要面对,那就是装修。对新房进行装修并没有改变房屋用于居住的本质,但它可以让房子变得更漂亮、更温馨、更实用、更能满足居家的需求。在软件设计中,我们也有一种类似新房装修的技术可以对已有对象(新房)的功能进行扩展(装修),以获得更加符合用户需求的对象,使得对象具有更加强大的功能。这种技术对应于一种被称之为装饰模式的设计模式,本章将介绍用于扩展系统功能的装饰模式。
一.概述
装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为,在现实生活中,这种情况也到处存在,例如一张照片,我们可以不改变照片本身,给它增加一个相框,使得它具有防潮的功能,而且用户可以根据需要给它增加不同类型的相框,甚至可以在一个小相框的外面再套一个大相框。
定义
装饰模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,就增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。
Decorator Pattern:Attach additional responsibilities to an object dynamically keeping the same interface.Decorators provide a flexible alternative to subclassing for extending functionality.
结构
在装饰模式中,为了让系统具有更好的灵活性和可扩展性,我们通常会定义一个抽象装饰类,而将具体的装饰类作为它的子类,装饰模式结构如图所示:
在装饰模式结构图中包含如下几个角色:
- Component(抽象构件):它是具体构件和抽象装饰类的共同父类,声明了在具体构件中实现的业务方法,它的引入可以使客户端以一致的方式处理未被装饰的对象以及装饰之后的对象,实现客户端的透明操作。
- ConcreteComponent(具体构件):它是抽象构件类的子类,用于定义具体的构件对象,实现了在抽象构件中声明的方法,装饰器可以给它增加额外的职责(方法)。
- Decorator(抽象装饰类):它也是抽象构件类的子类,用于给具体构件增加职责,但是具体职责在其子类中实现。它维护一个指向抽象构件对象的引用,通过该引用可以调用装饰之前构件对象的方法,并通过其子类扩展该方法,以达到装饰的目的。
- ConcreteDecorator(具体装饰类):它是抽象装饰类的子类,负责向构件添加新的职责。每一个具体装饰类都定义了一些新的行为,它可以调用在抽象装饰类中定义的方法,并可以增加新的方法用以扩充对象的行为。
由于具体构件类和装饰类都实现了相同的抽象构件接口,因此装饰模式以对客户透明的方式动态地给一个对象附加上更多的责任,换言之,客户端并不会觉得对象在装饰前和装饰后有什么不同。装饰模式可以在不需要创造更多子类的情况下,将对象的功能加以扩展。
实现
装饰模式的核心在于抽象装饰类的设计,其典型代码如下所示
public class Decorator implements 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()方法并根据需要进行扩展,典型的具体装饰类代码如下:
public class ConcreteDecorator