zoukankan      html  css  js  c++  java
  • Java设计模式--装饰器模式到Java IO 流

    装饰器模式

    抽象构件角色:给出一个抽象接口,以规范准备接受附加责任的对象。

    具体构件角色:定义准备接受附加责任的对象。

    抽象装饰角色:持有一个构件对象的实例,并对应一个与抽象构件接口一致的接口。

    具体装饰角色:负责给具体构件加上额外的责任。

    什么时候使用:

    1. 需要扩展一个类的功能,或者给一个类增加附加责任。

    2. 需要动态的给一个对象增加功能,这些功能可以再动态的撤销。

    3. 需要增加由一些基本功能的排列组合而产生的的大量的功能,从而使继承关系变得不现实。

    我以给汽车换颜色为例:

    汽车厂生产汽车实例,4S店可以喷漆换颜色。

    Car接口:

    /**
     * Created by 001977 on 2019-04-12 11:39.
     * 抽象构件角色
     */
    public interface Car {
    
        /**
         * 出厂车身颜色
         */
        void skin();
    }

    具体构件卡罗拉:

    /**
     * Created by 001977 on 2019-04-12 11:42.
     * 具体构件:COROLLA卡罗拉(灰色)
     */
    public class Corolla implements Car {
    
        @Override
        public void skin() {
            System.out.println("超级无敌灰色");
        }
    }

    4S店抽象装饰器:

    /**
     * Created by 001977 on 2019-04-12 11:45.
     * 抽象装饰角色(4S店)
     */
    public abstract class FourS implements Car {
    
        private Car car;
    
        public FourS(Car car) {
            this.car = car;
        }
    
        @Override
        public void skin() {
            car.skin();
        }
    }

    具体装饰器:喷枪红

    /**
     * Created by 001977 on 2019-04-12 11:49.
     * 具体装饰角色(红色喷漆)
     */
    public class RedSprayPaint extends FourS {
    
        public RedSprayPaint(Car car) {
            super(car);
        }
    
        @Override
        public void skin() {
            super.skin();
            System.out.println("花2000块钱喷红色的漆");
        }
    }

    具体装饰器:喷枪白

    /**
     * Created by 001977 on 2019-04-12 11:49.
     * 具体装饰角色(白色喷漆)
     */
    public class WhiteSprayPaint extends FourS {
    
        public WhiteSprayPaint(Car car) {
            super(car);
        }
    
        @Override
        public void skin() {
            super.skin();
            System.out.println("花1000块钱喷白色的漆");
        }
    }

    测试运行:

    public class Main {
        public static void main(String[] args) throws IOException {
            System.out.println("====================出厂颜色====================");
            Car corolla = new Corolla();
            corolla.skin();
            System.out.println("====================换颜色====================");
            RedSprayPaint red = new RedSprayPaint(new WhiteSprayPaint(corolla));
            red.skin();
        }
    }

    IO中的体现(以InputStream为例)

    抽象构件角色:由InputStream扮演,这个抽象类为各种子类型流处理器提供统一的接口。

    具体构件角色:由FileInputStream、ObjectInputStream 、ByteArrayInputStream 等原始流处理器扮演,他们实现了InputStream的接口,可以被装饰器装饰。

    抽象装饰角色:由FilterInputStream扮演,他也实现了InputStream的接口。

    具体装饰角色:由DataInputStream 、BufferedInputStream等扮演。

    ..

    由于IO库中需要很多性能的各种组合,如果用继承方法实现,那么每一种组合都需要一个类,这样会造成大量性能重复的类出现。如果使用装饰器模式,那么类的数目大大减少,性能的重复也减到最少。因此装饰器模式是IO中的基本模式。

    以InputStream【抽象构件】为例:上图中的流可以分为两类:原始流处理器【具体构件】(FileInputStream及其左边的类)和链接流处理器【装饰器】(实现FilterInputStream的类【具体装饰器】)。

    首先InputStream定义了一些规范:

    接着比如FileInputStream去实现,实际上它都是去调用本地方法的,请看:

    然后装饰器也去实现InputStream的方法,关键是持有InputStream对象的实例

     

    最后具体的装饰器比如:

    BufferedInputStream装饰了InputStream的内部工作方式,使得流的读入操作使用缓冲机制,不会对每一次流读入的操作都产生一次物理读盘动作,从而提高了程序的效率。它的内部有个buf字节数组用来缓存数据。

    读取的时候调用fill方法,简单来说就是先尝试获取缓冲区,然后再操作输入流将数据读入缓冲区,这期间还有一些细节比如调整pos不再赘述。

    还有DataInputStream提供了一些直接读取某种类型的数据的方法,省的我们读取完再去做转换。

    比如:readBoolean

    它的读入操作read方法就是直接调用原始流处理器的方法,并不复杂

     最后附上一张画了一天的IO继承关系图:

     如果图片看不清,鼠标右键---在新标签页下打开图片

  • 相关阅读:
    <<< Tomcat运行报错IOException while loading persisted sessions: java.io.EOFException
    <<< Tomcat 部署项目There are no resources that can be added or removed from the server
    <<< tomcat启动报错StandardServer.await: create[8005]
    【LeetCode】最接近的三数之和【排序,固定k1,二分寻找k2和k3】
    【LeetCode】三数之和【排序,固定一个数,然后双指针寻找另外两个数】
    【LeetCode】最长公共前缀【二分】
    【LeetCode】盛最多水的容器【双指针+贪心 寻找最大面积】
    【LeetCode】整数反转【不能借助辅助空间,需要处理溢出】
    【LeetCode】最长回文子串【动态规划或中心扩展】
    【LeetCode】寻找两个有序数组的中位数【性质分析+二分】
  • 原文地址:https://www.cnblogs.com/LUA123/p/10685693.html
Copyright © 2011-2022 走看看