(一)模式概念
装饰模式是指在不必改变原始类和不使用继承的情况下,通过创建一个包装对象,在包装对象中引用原始类以实现扩展原始类的功能。
该模式与对象适配器模式单从代码结构上来说基本一致,甚至两者都可叫做包装模式。但是从业务上来说,两者就有区别了,适配器模式着重于接口,适配用户对旧接口的不满足的需求;装饰模式则是对现有对象的功能进行升级增强。举个例子:如书店卖道德经这本书,适配器模式就是中文版还是韩文版,书本的文字不同;装饰模式则是普通版和珍藏版,书本文字内容相同,但装订方式不一样,通常来说珍藏版装订要比普通版更高级。
(注)装饰模式通常会创建一个新对象来包装原对象,通过新对象实现功能动态扩展。虽然用过继承也可以实现类似的效果,但由于Java不支持多继承,所以装饰模式可以提供比继承更多的灵活性。
(二)模式结构
1)抽象对象
定义基本的函数和变量
2)原始类
继承对象并实现基本函数
3)装饰类
继承抽象对象,在构造时引入原始类并在需求被装饰的函数中通过引用原始类并增加额外功能代码的方式增强被装饰的函数。
(三)Demo
ISource接口:
public interface ISource {
public void method();
}
抽象对象:public abstract class AbsSource implements ISource {
public void method() {
};
}
原始类:
public class Source extends AbsSource{
@Override
public void method() {
System.out.println("this is Source!");
}
}
DecoratorA装饰类,目的增强Source实体类的method方法。public class DecoratorA extends AbsSource{
private ISource source; // 引用被增强的实体类
public DecoratorA(ISource $source) {
source = $source;
}
@Override
public void method() {
source.method();
System.out.println("add D1 Method!");
}
}
DecoratorB装饰类,目的在DecoratorA基础上再次增强Source实体类的method方法。public class DecoratorB extends AbsSource {
private ISource source; // 引用被增强的实体类
public DecoratorB(ISource $source) {
source = $source;
}
@Override
public void method() {
source.method();
System.out.println("add D2 Method!");
}
}
执行过程:ISource s = new Source();
s.method();
System.out.println("-------------------");
ISource a = new DecoratorA(s);
a.method(); // 增强了D1方法
System.out.println("-------------------");
ISource b = new DecoratorB(a); // 增强了D2方法
b.method();
执行结果:this is Source!
-------------------
this is Source!
add D1 Method!
-------------------
this is Source!
add D1 Method!
add D2 Method!
可见,Source、DecoratorA、DecoratorB实现的是相同的接口,执行的method功能却不一样。DecoratorA是对Source的装饰,DecoratorB则是对DecoratorA的装饰,都增强了功能。