Java之装饰者模式实现

引言

装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为。

这个模式我们应当最清楚不过了,不管是在写IO流时候还是在java.awt.Container#add(Component) (几乎广泛存在于 Swing 组件中)javax.faces.component.UIComponent#getChildren() (几乎广泛存在于 JSF UI 组件中)
那么我们自己写一个简单的例子来认识它

案例 读写文件

需求说明

我需要一个功能,不仅仅只是原模原样的读写文件,我有时候需要压缩或者手动加密

成员

Client:调用者
CompressionDecorator:压缩装饰
DataSource:读写文件接口
DataSourceDecorator:读写文件装饰类,这个是用来接收其他装饰对象来调用它的装饰方法
EncryptionDecorator:加密装饰
FileDataSource:最基本的文件读写

							DataSource
public interface DataSource {
    void writeData(String data);

    String readData();
}
							DataSourceDecorator
public class DataSourceDecorator implements DataSource{

    private DataSource wrappee;

    public DataSourceDecorator(DataSource wrappee) {
        this.wrappee = wrappee;
    }

    @Override
    public void writeData(String data) {
        wrappee.writeData(data);
    }


    @Override
    public String readData() {
        return wrappee.readData();
    }
}

							CompressionDecorator
public class CompressionDecorator extends DataSourceDecorator {
    private int compLevel = 6;

    public CompressionDecorator(DataSource wrappee) {
        super(wrappee);
    }

    @Override
    public void writeData(String data) {
        super.writeData(compress(data));
    }

    @Override
    public String readData() {
        return decompress(super.readData());
    }

    private String decompress(String readData) {

        byte[] decode = Base64.decode(readData.getBytes());
        InputStream in = new ByteArrayInputStream(decode);
        InflaterInputStream inflaterInputStream = new InflaterInputStream(in);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(512);
        int len;
        try {
            while ((len = inflaterInputStream.read()) != -1) {
                byteArrayOutputStream.write(len);
            }
            in.close();
            inflaterInputStream.close();
            byteArrayOutputStream.close();
            return new String(byteArrayOutputStream.toByteArray());
        } catch (IOException e) {
            return null;
        }

    }

    private String compress(String data) {
        byte[] bytes = data.getBytes();
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream(512);
            DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(outputStream, new Deflater(compLevel));
            deflaterOutputStream.write(bytes);
            outputStream.close();
            deflaterOutputStream.close();
            return Base64.encode(outputStream.toByteArray());
        } catch (IOException ignored) {
            return null;
        }
    }

    public int getCompLevel() {
        return compLevel;
    }

    public CompressionDecorator setCompLevel(int compLevel) {
        this.compLevel = compLevel;
        return this;
    }
}
						EncryptionDecorator
public class EncryptionDecorator extends DataSourceDecorator {
    public EncryptionDecorator(DataSource wrappee) {
        super(wrappee);
    }

    @Override
    public void writeData(String data) {
        super.writeData(encode(data));
    }

    @Override
    public String readData() {
        return decode(super.readData());
    }

    private String encode(String data){
        byte[] bytes = data.getBytes();
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] += 1;
        }
        return Base64.encode(bytes);

    }
    private String decode(String data){
        byte[] decode = Base64.decode(data.getBytes());
        for (int i = 0; i < decode.length; i++) {
            decode[i] -= 1;
        }
        return new String(decode);
    }
}

								FileDataSource
public class FileDataSource implements DataSource{

    private String name;

    public FileDataSource(String name) {
        this.name = name;
    }

    @Override
    public void writeData(String data) {
        try {
            OutputStream outputStream = new FileOutputStream(new File(name));
            outputStream.write(data.getBytes(),0,data.length());
        } catch (FileNotFoundException e) {
            System.out.println(e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @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());
        }
        assert buffer != null;
        return new String(buffer);
    }
}

									Client
public class Client {
    public static void main(String[] args) {
        String salaryRecords = "装饰模式是一种结构型设计模式, 允许你通过将对象放入包含行为的特殊封装对象中来为原对象绑定新的行为";
        DataSourceDecorator encoded =
                new CompressionDecorator(new EncryptionDecorator(new FileDataSource("e:/OutputDemo.txt")));
        encoded.writeData(salaryRecords);
        System.out.println(encoded.readData());
        DataSource plain = new FileDataSource("e:/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());
    }
}

执行结果
在这里插入图片描述
这个例子中就可以发现压缩装饰或者加密装饰有很大的扩展性,可以删去也可以加一些其他的装饰来满足你的需求

结束语

装饰者模式目的就在于不再扩展局限于继承类这个地方,而是使用一种很巧妙的方式来加厚或减薄
你可以穿脱衣服来让你自己感觉舒适,代码也可以

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值