定义:Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality. 简而言之就是,在保持同一个功能接口不变的情况下动态的为对象添加新的功能,就被称为装饰模式。
故事:下面将用一个例子说明采用装饰模式来灵活为对象增加功能的方便之处。故事情景为推销一本书。如何才能灵活不断地添加新的推销词,来“装饰”你这本书,这就是我们装饰模式所要做的。
一般方式:采用添加子类的方式,覆写父类的推销方法来达到修饰原有说辞的目的。然而一旦需要再次添加新的修饰词,按照这种思路我们只能不断地继承子类,覆写上一级父类的推销方法,达到我们的目的。采用这种方式,一旦类之间的继承关系超过三重,乃至更多,一旦我们想更改以前的功能模块,则调试起来将极为不便。这种传统思维下,系统的可扩展性将极差。
装饰模式::其基本思想在于:
- 首先创建一个抽象类或接口,作为待修饰的基本核心类,例如本例中的书,定义推销方法promote()
- 然后,由继承该抽象类(或接口),创建具体的待修饰实体类,例如本例中的小说,以及采用代理模式的思想创建修饰类的抽象父类。
- 具体修饰类均继承自该修饰类的抽象父类,并覆写父类方法,达到修饰的作用。
类图如下:
其代码如下:
Compoment.java
/**
* Created by Song on 2016/8/31.
* 核心抽象基础类
*/
public abstract class Component {
//推销方法
public abstract void promote();
}
ConcreteComponent.java
/**
* Created by Song on 2016/8/31.
* 具体待装饰类
*/
public class ConcreteComponent extends Component {
@Override
public void promote() {
System.out.println("这是一本书,售价99元");
}
}
Decorator.java
/**
* Created by Song on 2016/8/31.
* 装饰基类,采用代理模式,传入待装饰对象
*/
public class Decorator extends Component {
//装饰对象
private Component component;
//构造函数
public Decorator(Component component){
this.component = component;
}
@Override
public void promote() {
this.component.promote();
}
}
NumDecorator.java
/**
* Created by Song on 2016/8/31.
* 销量装饰器
*/
public class NumDecorator extends Decorator {
public NumDecorator(Component component){
super(component);
}
@Override
public void promote() {
super.promote();
System.out.println("本书销量本年度第一,达到一亿册哟!!");
}
}
PriceDecorator.java
/**
* Created by Song on 2016/8/31.
* 价格装饰类
*/
public class PriceDecorator extends Decorator {
//构造函数
public PriceDecorator(Component component){
super(component);
}
@Override
public void promote() {
super.promote();
System.out.println("原价可是999元哦!!");
}
}
测试类:
/**
* Created by Song on 2016/8/31.
*/
public class Main {
public static void main(String [] args){
Component component;
//得到基本待修饰对象
component = new ConcreteComponent();
//首次修饰
component = new PriceDecorator(component);
//再一次修饰
component = new NumDecorator(component);
//打印修饰后的推销辞令
component.promote();
}
}
结果:
模式优点:
- 系统扩展性非常好,在需要“打补丁”的应用环境下,它可以作为采用多级继承关系的替代方案。装饰类和待装饰类可以相互独立发展,而不会相互耦合。
- 装饰模式可以动态地扩展一个类的功能
注意事项:还是需要尽量减少装饰类的数量,否则系统复杂性将大幅度 提升,在多层装饰模式下,排查问题所耗用的时间也将激增。
一句话总结:在想到采用继承扩展已有类的功能时,请立刻想到更好地去采用装饰模式实现。