设计模式——装饰器模式

153 阅读2分钟

1. 装饰器模式概述

装饰器模式又叫装饰者模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。

(1) 适用情况

动态地给一个对象添加一些额外的职责。

(2) 优点

相比于生成子类更加灵活,减少了装饰者和被装饰者之间的耦合。

(3) 缺点

若装饰器过多,会使得系统变的复杂。

2. 装饰器模式实例

最常见的例子,就是I/O流。
Java中把不同的输入/输出源抽象为流,可以分为字节流和字符流。
字节流是把1个字节作为一个处理单元,主要用来处理byte类型的数据;
字符流是把2个字符作为一个处理单元,它是把编码集对字节流翻译之后的产物,用来处理中文等。

(1) 字节流

面向字节的输入流为InputStream,输出流为OutputStream;
但是它们都是抽象类,需要有对应的子类实现,比如用来处理文件的FileInputStream和FileOutputStream;
而BufferedInputStream和BufferedOutputStream可以为输入/输出流添加一些功能,比如提供缓冲功能,支持mark标记和reset重置方法等,这就是用到了装饰器模式的思想。

public class ByteStreamDemo {
    public static void main(String[] args) {
        try {
            // 生成文件对象
            File file = new File("D:/test.txt");
            // 创建输出流
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            // 创建缓冲输出流
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
            // 写数据
            bufferedOutputStream.write("Hello World!".getBytes());
            // 释放资源
            bufferedOutputStream.close();

            // 创建输入流
            InputStream inputStream = new FileInputStream(file);
            // 创建缓冲输入流
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            // 读数据
            int len;
            while ((len = bufferedInputStream.read()) != -1) {
                System.out.print((char) len);
            }
            // 释放资源
            bufferedInputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

(2) 字符流

面向字符的输入流为Reader,输出流为Writer;
InputStreamReader和OutputStreamWriter可以将字节输入/输出流转化为字符输入/输出流;
BufferedReader和BufferedWriter提供了缓冲功能;
FileReader和FileWriter可以用来处理文件;
这都用到了装饰器模式的思想。

public class CharacterStreamDemo {
    public static void main(String[] args) {
        try {
            // 生成文件对象
            File file = new File("D:/hello.txt");
            // 创建输出流
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            // 字节流转为字符流
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
            // 创建缓冲输出流
            BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
            // 写数据
            bufferedWriter.write("你好");
            // 释放资源
            bufferedWriter.close();

            // 创建输入流
            FileInputStream fileInputStream = new FileInputStream(file);
            // 字节流转为字符流
            InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
            // 创建缓冲输入流
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            // 读数据
            String read;
            while ((read = bufferedReader.readLine()) != null) {
                System.out.print(read);
            }
            // 释放资源
            bufferedReader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. 一些思考

在适配器模式中,我们专门创建了适配器类,来调用被适配的类的方法。而在装饰器模式中,我们只是使用被装饰者来构造装饰者,这两者感觉确实很像。

参考引用

装饰者模式:www.runoob.com/design-patt…