三、装饰者模式

定义:动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。

这里写图片描述

  • 个人理解

    1、装饰者存在两个重要的组成部分,需要被装饰的组件(被装饰者)和装饰者抽象。每个装饰者需要持有一个组件,也就是说,装饰者需要持有Component抽象的引用。
    2、装饰者和被装饰者必须是一样的类型也就是要有共同的超类,这是装饰者模式的关键。(因为装饰者必须要能取代被装饰者)
    3、在以上 的类图中,继承Beverage类,是为了有正确的类型,而不是继承它的行为。行为来自于装饰者和基础组件。或者其他装饰者之间的组合关系。(如果依赖继承,那么类的行为只能在编译时静态决定,也就是说,行为不是来自于超类就是子类覆盖后的版本)

  • 要点
    1、继承属于扩展形式之一,但不见得是达到弹性的最佳方案。
    2、在我们的设计中,应该允许行为可以被扩展,而无需修改现有的代码
    3、组合和委托可以在运行时动态地加上新的行为。
    4、除了继承,装饰者模式也可以让我们扩展行为。
    5、装饰者模式以为者一群装饰者类,这些类用来包装具体组件 。
    6、装饰者类反应出被装饰者的组件类型(事实上,他们具有相同的类型,都通过接口或继承实现)。
    7、装饰者可以在被装饰者的行为前面/或后面加上自己的行为,甚至将被装饰者的行为整个取代掉,而达到特定的目的。
    8、你可以用无数个装饰者包装一个组件。
    9、装饰者一般对组件的客户是透明的,除非客户程序依赖于具体的组件。
    10、装饰者会导致设计中出现很多小的对象,如果过度使用,会让程序变得复杂。

  • Java IO 的简单类图UML

使用装饰者模式,建立一个新的装饰者完成实现将字符串的小写变成大写。

  • LowerCaseInputStream 类,实现将字符的小写变成大写。
public class LowerCaseInputStream extends FilterInputStream {

    public LowerCaseInputStream(InputStream in) {
        super(in);
    }

    public int read() throws IOException {
        int c = super.read();
        return (c == -1 ? c : Character.toLowerCase((char)c));
    }

    public int read(byte[] b, int offset, int len) throws IOException {
        int result = super.read(b, offset, len);
        for (int i = offset; i < offset+result; i++) {
            b[i] = (byte)Character.toLowerCase((char)b[i]);
        }
        return result;
    }
}
  • 测试类
public class InputTest {
    public static void main(String[] args) throws IOException {
        int c;
        try {
            InputStream in = new LowerCaseInputStream(new BufferedInputStream(new FileInputStream("test.txt")));
            while ((c = in.read()) >= 0) {
                System.out.print((char) c);
            }
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

说明:以上代码来自于HeadFirst书籍智慧,请参考原书,获得更多知识。

原文地址:https://www.cnblogs.com/huacesun/p/6622492.html