Java设计模式之Decorator装饰器模式

本来想写 Java 中 IO 库的文章,总结一下,因为看到 Java IO 中所使用的装饰器模式, 因为手头有之前的资料,所以先记录一篇关于 装饰器模式的文章,回头再好好补一下 IO 部分的文章。

废话先不多说,上图

Java Decorator

图中很明显 DemoComponent 是接口,由 DemoComponentImplA 和 DemoComponentImplB 分别实现。

抽象类 Decorator 也实现 DemoComponent 接口, DecoratorA 和 DecoratorB 集成自 抽象类 Decorator, 并且 抽象类 Decorator 含有一个 DemoComponent, 是组合关系。

这个时候, DemoComponent 的任何一个方法,都会由 DemoComponentImplA 、DemoComponentImplB 和 Decorator 实现。

然后,因为 DecoratorA 和 DecoratorB 继承自 Decorator, 那么也会实现该方法。那么 DecoratorA 和 DecoratorB 这两个具体的装饰器实现类,可以在 DemoComponent 的方法内添油加醋,就是所谓的装饰。

代码栗子:

DemoComponent 接口

public interface DemoComponent {
    public void showMe();
}

实现实体类 DemoComponentImplA

public class DemoComponentImplA implements DemoComponent {
    @Override
    public void showMe() {
        System.out.println("This is DemoComponentImplA");
    }
}

实现实体类 DemoComponentImplB

public class DemoComponentImplB implements DemoComponent {
    @Override
    public void showMe() {
        System.out.println("This is DemoComponentImplB");
    }
}

以上是需要装饰的实体类,一个接口, 两个实现,方法名为 showMe()

抽象装饰类 Decorator, 这个地方 不仅实现 DemoComponent, 并且将 DemoComponent 作为属性,也就是含有 DemoComponent 对象, 同时作为构造函数的参数,把外部的需要装饰的对象,加载到这个属性上。

public abstract class Decorator implements DemoComponent {
    protected DemoComponent component;
    public Decorator(DemoComponent component) {
        super();
        this.component = component;
    }
    @Override
    public void showMe() {
        this.component.showMe();
    }
}

装饰器类 DecoratorA, 是真正装饰 实体类的 类, 比较拗口。。。

这里集成了父类的属性,所以当 super.showMe() 操作时,实际是做了 DemoComponent 的方法,这里就是添油加醋的地方。

public class DecoratorA extends Decorator {
    public DecoratorA(DemoComponent component) {
        super(component);
    }
    public void showMeA() {
        System.out.println("This is Decorator A new...");
    }
    @Override
    public void showMe() {
        System.out.println("This is Decorator A before...");
        super.showMe();
        System.out.println("This is Decorator A after...");
    }
}

装饰器 DecoratorB, 跟 A 一样,为了显示装饰不同的内容

public class DecoratorB extends Decorator {
    public DecoratorB(DemoComponent component) {
        super(component);
    }
    public void showMeB() {
        System.out.println("This is Decorator B new...");
    }
    @Override
    public void showMe() {
        System.out.println("This is Decorator B before...");
        super.showMe();
        System.out.println("This is Decorator B after...");
    }
}

然后就是测试类

public class DemoDecorator {
    public static void main(String args[]) {
        //2个实体类初始化
        DemoComponent comA = new DemoComponentImplA();
        DemoComponent comB = new DemoComponentImplB();
        System.out.println("==============================");
        //打印一下,里面的内容
        comA.showMe();
        comB.showMe();
        System.out.println("==============================");
        //2个装饰类初始化,参数是刚才定义的2个实体类,注意,这里没有修改2个实体类
        DecoratorA comDecA = new DecoratorA(comA);
        DecoratorA comDecB = new DecoratorA(comB);
        //分别调用被装饰的 showMe() 方法 和 装饰器的新方法  showMeA(), 以显示不同之处
        comDecA.showMe();
        comDecB.showMe();
        comDecA.showMeA();
        comDecB.showMeA();
        System.out.println("==============================");
        //下面代码就同上了
        DecoratorB comDecAA = new DecoratorB(comA);
        DecoratorB comDecBB = new DecoratorB(comB);
        comDecAA.showMe();
        comDecBB.showMe();
        comDecAA.showMeB();
        comDecBB.showMeB();
    }
}

输出如下

==============================
This is DemoComponentImplA
This is DemoComponentImplB
==============================
This is Decorator A before...
This is DemoComponentImplA
This is Decorator A after...
This is Decorator A before...
This is DemoComponentImplB
This is Decorator A after...
This is Decorator A new...
This is Decorator A new...
==============================
This is Decorator B before...
This is DemoComponentImplA
This is Decorator B after...
This is Decorator B before...
This is DemoComponentImplB
This is Decorator B after...
This is Decorator B new...
This is Decorator B new...

总结:

来看看 Java IO 里面的内容。

FilterInputStream,FilterOutputStream,FilterRead,FilterWriter分别为具体装饰器的父类,相当于Decorator类,它们分别实现了InputStream,OutputStream,Reader,Writer类(这些类相当于DemoComponent,是其他实体类的接口类,Decorator实现了该接口)。

继承自InputStream,OutputStream,Reader,Writer这四个类的其他类是具体的组件类,每个都有相应的功能,相当于DemoComponentImplA类。

而继承自FilterInputStream,FilterOutputStream,FilterRead,FilterWriter这四个类的其他类就是具体的装饰器对象类,即DemoComponentImplA类。

通过这些装饰器类,可以给我们提供更加具体的有用的功能。如FileInputStream是InputStream的一个子类,从文件中读取数据流,BufferedInputStream是继承自FilterInputStream的具体的装饰器类,该类提供一个内存的缓冲区类保存输入流中的数据。

下面是摘自网络的装饰器使用准则或者惯例:

(1)需要在不影响其他对象的情况下,以动态、透明的方式给对象添加职责。

(2)如果不适合使用子类来进行扩展的时候,可以考虑使用装饰器模式。