在学习这一节之前其实大家已经或多或少的接触过装饰器模式了,比如IO中的InputStream、FileInputStream、ServletInputStream等等其组合使用时就是装饰器模式了,比如下面的代码就是一个例子:
InputStream input = new GZIPInputStream( // 第二层装饰
new BufferedInputStream( // 第一层装饰
new FileInputStream("logictime2.gz") // 核心功能
));
对于装饰器模式,如果用一张图进行说明的话就是这样子的:
Component: 一般是接口或者抽象类,定义了最简单的方法,装饰器类和被装饰类都要实现该接口。
ComponentA/ComponentB: 被装饰类,实现了Component。
Decorator: 装饰器类,通过该类为ComponentA/ComponentB动态添加额外的方法,实现了Component接口,并且该对象中持有一个Component的成员变量。
DecoratorA/DecoratorB: 具体的装饰类,该类中的方法就是要为Component动态添加的方法。
第一个例子是将这张图与IO进行一下比较关联:
最顶层的Component是接口,对应到IO的就是InputStream这个抽象类。ComponentA、ComponentB是实际的子类,对应到IO的就是FileInputStream、ServletInputStream这些数据源。Decorator是用于实现各个附加功能的抽象装饰器,对应到IO的就是FilterInputStream。而从Decorator派生的就是一个一个的装饰器,它们每个都有独立的功能,对应到IO的就是BufferedInputStream、GZIPInputStream等。
第二个例子我们来自己动手实现一个decorator:
第一步:我们实现Compoent接口以及他的一个子类ComponentA;
public interface Shoes {
public void makeShoes();
}
public class MakeShoes implements Shoes {
@Override
public void makeShoes() {
System.out.println("制作一双鞋");
}
}
第二步:我们实现Decorator:
public class Decorator implements Shoes {
private Shoes shoes;
public Decorator(Shoes _shoes) {
this.shoes = _shoes;
}
@Override
public void makeShoes() {
shoes.makeShoes(); //基本功能委派给其他类实现
}
}
第三步:完成decorator的两个具体子类,进行功能拓展:
public class Embroidery extends Decorator {
public Embroidery(Shoes _shoes) {
super(_shoes);
}
public void embroidery() {
System.out.println("给鞋补充图案");
}
public void makeShoes() {
super.makeShoes();
//拓展方式一:直接在子类的基本功能的实现方法中更新
System.out.println("在鞋子上绘制一个logo");
//拓展方式二:在子类中新加入一个方法,在基本功能的实现方法中调用
this.embroidery();
}
}
public class Hollow extends Decorator {
public Hollow(Shoes _shoes) {
super(_shoes);
}
public void hollow() {
System.out.println("关键位置挖层处理");
}
public void makeShoes() {
super.makeShoes();
this.hollow();
}
}
第四步:在客户端中进行测试,基本功能的实现以及功能的组装:
public class TestDecorator {
public static void main(String[] args) {
Shoes shoes = new MakeShoes();
shoes = new Embroidery(shoes);
shoes = new Hollow(shoes);
shoes.makeShoes();
//当然我们也可以这么实现:
Shoes shoes = new Hollow(new Embroidery(new MakeShoes()));
shoes.makeShoes();
System.out.println("鞋子制作完成!");
}
}
至此为止,一个装饰器模式的实现已经完成了。
设计框架:
使用装饰器的优点在于:
如果我们要新增核心功能,就增加Component的子类,例如ByteInputStream。如果我们要增加附加功能,就增加Decorator的子类,例如CipherInputStream。两部分都可以独立地扩展,而具体如何附加功能,由调用方自由组合,从而极大地增强了灵活性。
总结:
使用Decorator模式,可以独立增加核心功能,也可以独立增加附加功能,二者互不影响;可以在运行期动态地给核心功能增加任意个附加功能。其中增加功能可以通过在装饰器的具体子类中增加一个方法然后在原有功能的方法覆写时调用,也可以直接对原有功能覆写然后增加代码语句进行修改。