• 设计模式之装饰者模式


    前言

    本节从装饰者模式到Java 里的 IO。装饰者模式能够在不修改任何底层类代码的情况下,给你的(或别人的) 对象赋予新的职责。属于结构型设计模式。符合开闭原则,但是会产生更多的类,提高程序复杂性。

    代码实现

    // 抽象实体类
    public abstract class Cake {
    
        protected abstract String getDesc();
    
        protected abstract int cost();
    }
    
    // 确定的实体类
    public class RelCake extends Cake {
        @Override
        public String getDesc() {
            return "这是一个蛋糕";
        }
    
        @Override
        public int cost() {
            return 150;
        }
    }
    
    // 抽象装饰者
    public abstract class Decorator extends Cake {
        private Cake cake;
    
        public Decorator(Cake cake) {
            this.cake = cake;
        }
    
        // 抽象装饰者可以通过此方法保证装饰者实现此方法 (拓展)
        // protected abstract void doSomething();
    
        @Override
        public String getDesc() {
            return cake.getDesc();
        }
    
        @Override
        public int cost() {
            return cake.cost();
        }
        
    }
    
    
    // 具体装饰者
    // 往蛋糕里面加葡萄
    public class CakeWithGrapes extends Decorator {
        public CakeWithGrapes(Cake cake) {
            super(cake);
        }
    
        @Override
        public String getDesc() {
            return super.getDesc() + " 加一份葡萄";
        }
    
        @Override
        public int cost() {
            return super.cost() + 20;
        }
    }
    // 往蛋糕里加草莓
    public class CakeWithStra extends Decorator {
    
        public CakeWithStra(Cake cake) {
            super(cake);
        }
    
        @Override
        public String getDesc() {
            return super.getDesc() + " 加一份草莓";
        }
    
        @Override
        public int cost() {
            return super.cost() + 30;
        }
    }
    
    // 测试
    public class DecoratorTest {
        public static void main(String[] args) {
            // 声明抽象实体
            Cake cake;
            // 赋值具体实体
            cake = new RelCake();
            // 进行装饰
            cake = new CakeWithGrapes(cake);
            cake = new CakeWithGrapes(cake);
            cake = new CakeWithStra(cake);
            System.out.println(cake.getDesc() + "价钱:" + cake.cost());
        }
    }
    

    UML

    角色:抽象的实体类,确定的实体类。抽象的装饰者,确定的装饰者。
    装饰者模式

    Java I/O

    InputStream 作为基类,抽象组件

    一类是直接提供数据的基础InputStream:抽象装饰者

    • FileInputStream
    • ByteArrayInputStream
    • ServletInputStream
    • ...

    一类是提供额外附加功能的InputStream:具体装饰者

    • BufferedInputStream
    • DigestInputStream
    • CipherInputStream
    • ...

    当我们需要给一个“基础”InputStream附加各种功能时,我们先确定这个能提供数据源的InputStream,因为我们需要的数据总得来自某个地方,例如,FileInputStream,数据来源自文件:

    InputStream file = new FileInputStream("test.gz");

    紧接着,我们希望FileInputStream能提供缓冲的功能来提高读取的效率,因此我们用BufferedInputStream包装这个InputStream,得到的包装类型是BufferedInputStream,但它仍然被视为一个InputStream:

    InputStream buffered = new BufferedInputStream(file);

    无论我们包装多少次,得到的对象始终是InputStream

    注意到在叠加多个FilterInputStream,我们只需要持有最外层的InputStream,并且,当最外层的InputStream关闭时(在try(resource)块的结束处自动关闭),内层的InputStream的close()方法也会被自动调用,并最终调用到最核心的“基础”InputStream,因此不存在资源泄露。

    自己实现一个 LowerCaseInputStream

    对文件中的字符串将大写字符小写处理

    // 拓展FilterInputStream 这是所有InputStream 的抽象装饰者
    public class LowerCaseInputStream extends FilterInputStream {
    
        protected LowerCaseInputStream(InputStream in) {
            super(in);
        }
    
        // 针对字节
        @Override
        public int read() throws IOException {
            int cur = super.read();
            return ((cur == -1) ? cur : Character.toLowerCase((char) cur));
        }
    
        // 针对字节数组
        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            int result = super.read(b, off, len);
            for (int i = off; i < off + result; i++) {
                b[i] = (byte) Character.toLowerCase((char) b[i]);
            }
            return result;
        }
    
    }
    
    
    public class FileTest {
        public static void main(String[] args) {
            int c;
            try {
                // 对 InputStream 的包装
                InputStream inputStream = new FileInputStream("yourPath\test.txt");
                inputStream = new BufferedInputStream(inputStream);
                inputStream = new LowerCaseInputStream(inputStream);
    
                // 读取字符进行输出
                while ((c = inputStream.read()) >= 0) {
                    System.out.print((char) c);
                }
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    test.txt 内容:What are you Doing now?

    控制台输出:what are you doing now?

    总结

    通过在继承上面加入组合的方式实现装饰。抽象策略将抽象实体用构造器传入,从而对抽象实体进行装饰。 可以在运行时给某个功能添加附加的功能。

    References

  • 相关阅读:
    docker容器中查看容器linux版本
    mac 安装docker
    音视频流处理
    激光雷达
    sick 激光
    Ubuntu 14.04 安装Docker
    W: GPG error: http://ppa.launchpad.net trusty InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 8CF63AD3F06FC659
    rtp发送 h265
    pytorch 环境搭建
    Linux 修改文件夹的用户组权限
  • 原文地址:https://www.cnblogs.com/wei57960/p/12941406.html
Copyright © 2020-2023  润新知