Java 装饰模式讲解和代码示例

简介: Java 装饰模式讲解和代码示例

使用示例装饰在 Java 代码中可谓是标准配置 尤其是在与流式加载相关的代码中

Java 核心程序库中有一些关于装饰的示例

  • java.io.InputStreamOutput­StreamReaderWriter 的所有代码都有以自身类型的对象作为参数的构造函数
  • java.util.Collectionschecked­XXX()synchronized­XXX() unmodifiable­XXX() 方法
  • javax.servlet.http.HttpServletRequestWrapper  Http­Servlet­Response­Wrapper

识别方法装饰可通过以当前类或对象为参数的创建方法或构造函数来识别

01编码和压缩装饰

本例展示了如何在不更改对象代码的情况下调整其行为

最初的业务逻辑类仅能读取和写入纯文本的数据 此后 我们创建了几个小的封装器类 以便在执行标准操作后添加新的行为

第一个封装器负责加密和解密数据 而第二个则负责压缩和解压数据

你甚至可以让这些封装器嵌套封装以将它们组合起来

02decorators

decorators/DataSource.java: 定义了读取和写入操作的通用数据接口

package refactoring_guru.decorator.example.decorators;public interface DataSource {    void writeData(String data);    String readData();
}

decorators/FileDataSource.java: 简单数据读写器

package refactoring_guru.decorator.example.decorators;import java.io.*;public class FileDataSource implements DataSource {    private String name;    public FileDataSource(String name) {        this.name = name;
    }    @Override
    public void writeData(String data) {        File file = new File(name);        try (OutputStream fos = new FileOutputStream(file)) {            fos.write(data.getBytes(), 0, data.length());
        } catch (IOException ex) {            System.out.println(ex.getMessage());
        }
    }    @Override
    public String readData() {        char[] buffer = null;        File file = new File(name);        try (FileReader reader = new FileReader(file)) {            buffer = new char[(int) file.length()];            reader.read(buffer);
        } catch (IOException ex) {            System.out.println(ex.getMessage());
        }        return new String(buffer);
    }
}

decorators/DataSourceDecorator.java: 抽象基础装饰

package refactoring_guru.decorator.example.decorators;public class DataSourceDecorator implements DataSource {    private DataSource wrappee;    DataSourceDecorator(DataSource source) {        this.wrappee = source;
    }    @Override
    public void writeData(String data) {        wrappee.writeData(data);
    }    @Override
    public String readData() {        return wrappee.readData();
    }
}

decorators/EncryptionDecorator.java: 加密装饰

package refactoring_guru.decorator.example.decorators;import java.util.Base64;public class EncryptionDecorator extends DataSourceDecorator {    public EncryptionDecorator(DataSource source) {        super(source);
    }    @Override
    public void writeData(String data) {        super.writeData(encode(data));
    }    @Override
    public String readData() {        return decode(super.readData());
    }    private String encode(String data) {        byte[] result = data.getBytes();        for (int i = 0; i < result.length; i++) {            result[i] += (byte) 1;
        }        return Base64.getEncoder().encodeToString(result);
    }    private String decode(String data) {        byte[] result = Base64.getDecoder().decode(data);        for (int i = 0; i < result.length; i++) {            result[i] -= (byte) 1;
        }        return new String(result);
    }
}

decorators/CompressionDecorator.java: 压缩装饰

package refactoring_guru.decorator.example.decorators;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.Base64;import java.util.zip.Deflater;import java.util.zip.DeflaterOutputStream;import java.util.zip.InflaterInputStream;public class CompressionDecorator extends DataSourceDecorator {    private int compLevel = 6;    public CompressionDecorator(DataSource source) {        super(source);
    }    public int getCompressionLevel() {        return compLevel;
    }    public void setCompressionLevel(int value) {        compLevel = value;
    }    @Override
    public void writeData(String data) {        super.writeData(compress(data));
    }    @Override
    public String readData() {        return decompress(super.readData());
    }    private String compress(String stringData) {        byte[] data = stringData.getBytes();        try {            ByteArrayOutputStream bout = new ByteArrayOutputStream(512);            DeflaterOutputStream dos = new DeflaterOutputStream(bout, new Deflater(compLevel));            dos.write(data);            dos.close();            bout.close();            return Base64.getEncoder().encodeToString(bout.toByteArray());
        } catch (IOException ex) {            return null;
        }
    }    private String decompress(String stringData) {        byte[] data = Base64.getDecoder().decode(stringData);        try {            InputStream in = new ByteArrayInputStream(data);            InflaterInputStream iin = new InflaterInputStream(in);            ByteArrayOutputStream bout = new ByteArrayOutputStream(512);            int b;            while ((b = iin.read()) != -1) {                bout.write(b);
            }            in.close();            iin.close();            bout.close();            return new String(bout.toByteArray());
        } catch (IOException ex) {            return null;
        }
    }
}

Demo.java: 客户端代码

package refactoring_guru.decorator.example;import refactoring_guru.decorator.example.decorators.*;public class Demo {    public static void main(String[] args) {        String salaryRecords = "Name,Salary\nJohn Smith,100000\nSteven Jobs,912000";        DataSourceDecorator encoded = new CompressionDecorator(                                         new EncryptionDecorator(                                             new FileDataSource("out/OutputDemo.txt")));        encoded.writeData(salaryRecords);        DataSource plain = new FileDataSource("out/OutputDemo.txt");        System.out.println("- Input ----------------");        System.out.println(salaryRecords);        System.out.println("- Encoded --------------");        System.out.println(plain.readData());        System.out.println("- Decoded --------------");        System.out.println(encoded.readData());
    }
}

OutputDemo.txt: 执行结果

-

Input ----------------
Name,Salary
John Smith,100000
Steven Jobs,912000
- Encoded --------------
Zkt7e1Q5eU8yUm1Qe0ZsdHJ2VXp6dDBKVnhrUHtUe0sxRUYxQkJIdjVLTVZ0dVI5Q2IwOXFISmVUMU5rcENCQmdxRlByaD4+
- Decoded --------------
Name,Salary
John Smith,100000
Steven Jobs,912000
相关文章
|
1天前
|
Java 编译器
滚雪球学Java(36):玩转Java方法重载和可变参数,让你的代码更灵活
【5月更文挑战第11天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
5 0
滚雪球学Java(36):玩转Java方法重载和可变参数,让你的代码更灵活
|
2天前
|
Java 测试技术
如何提高Java代码的可读性
Java是一种常用的编程语言,但是写出易懂且可读性高的代码却是一项挑战。本文将分享一些技巧和建议,帮助您提高Java代码的可读性和可维护性。
|
5天前
|
Java 索引
String字符串常用函数以及示例 JAVA基础
String字符串常用函数以及示例 JAVA基础
|
6天前
|
Java Kotlin
java调用kotlin代码编译报错“找不到符号”的问题
java调用kotlin代码编译报错“找不到符号”的问题
17 10
|
6天前
|
前端开发 Java Spring
Java Web ——MVC基础框架讲解及代码演示(下)
Java Web ——MVC基础框架讲解及代码演示
13 1
|
6天前
|
设计模式 前端开发 网络协议
Java Web ——MVC基础框架讲解及代码演示(上)
Java Web ——MVC基础框架讲解及代码演示
8 0
|
6天前
|
Java
Java的取余如何编写代码
【5月更文挑战第9天】Java的取余如何编写代码
22 5
|
6天前
|
Java
代码实例演示Java字符串与输入流互转
代码实例演示Java字符串与输入流互转
10 1
|
6天前
|
存储 安全 Java
掌握8条泛型规则,打造优雅通用的Java代码
掌握8条泛型规则,打造优雅通用的Java代码
掌握8条泛型规则,打造优雅通用的Java代码
|
6天前
|
Java 程序员 图形学
程序员教你用代码制作飞翔的小鸟--Java小游戏,正好拿去和给女神一起玩
《飞扬的小鸟》Java实现摘要:使用IntelliJ IDEA和JDK 16开发,包含小鸟类`Bird`,处理小鸟的位置、速度和碰撞检测。代码示例展示小鸟图像的加载、绘制与旋转。同时有`Music`类用于循环播放背景音乐。游戏运行时检查小鸟是否撞到地面、柱子或星星,并实现翅膀煽动效果。简单易懂,可直接复制使用。