• 装饰器模式


      装饰模式(Decorator),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。

      

     在装饰模式中的角色有:

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

      ●  具体构件(ConcreteComponent)角色:定义一个将要接收附加责任的类。

      ●  装饰(Decorator)角色:持有一个构件(Component)对象的实例,并定义一个与抽象构件接口一致的接口。

      ●  具体装饰(ConcreteDecorator)角色:负责给构件对象“贴上”附加的责任。

    InputStream类型中的装饰模式

      InputStream类型中的装饰模式是半透明的。为了说明这一点,不妨看一看作装饰模式的抽象构件角色的InputStream的源代码。这个抽象类声明了九个方法,并给出了其中八个的实现,另外一个是抽象方法,需要由子类实现。

    public abstract class InputStream implements Closeable {
    
        public abstract int read() throws IOException;
    
     
        public int read(byte b[]) throws IOException {}
    
        public int read(byte b[], int off, int len) throws IOException {}
    
        public long skip(long n) throws IOException {}
    
        public int available() throws IOException {}
        
        public void close() throws IOException {}
        
        public synchronized void mark(int readlimit) {}
        
        public synchronized void reset() throws IOException {}
    
        public boolean markSupported() {}
    
    }

      

      下面是作为装饰模式的抽象装饰角色FilterInputStream类的源代码。可以看出,FilterInputStream的接口与InputStream的接口是完全一致的。也就是说,直到这一步,还是与装饰模式相符合的。

    public class FilterInputStream extends InputStream {
        protected FilterInputStream(InputStream in) {}
        
        public int read() throws IOException {}
    
        public int read(byte b[]) throws IOException {}
        
        public int read(byte b[], int off, int len) throws IOException {}
    
        public long skip(long n) throws IOException {}
    
        public int available() throws IOException {}
    
        public void close() throws IOException {}
    
        public synchronized void mark(int readlimit) {}
    
        public synchronized void reset() throws IOException {}
    
        public boolean markSupported() {}
    }

      

      下面是具体装饰角色PushbackInputStream的源代码。

    public class PushbackInputStream extends FilterInputStream {
        private void ensureOpen() throws IOException {}
        
        public PushbackInputStream(InputStream in, int size) {}
    
        public PushbackInputStream(InputStream in) {}
    
        public int read() throws IOException {}
    
        public int read(byte[] b, int off, int len) throws IOException {}
    
        public void unread(int b) throws IOException {}
    
        public void unread(byte[] b, int off, int len) throws IOException {}
    
        public void unread(byte[] b) throws IOException {}
    
        public int available() throws IOException {}
    
        public long skip(long n) throws IOException {}
    
        public boolean markSupported() {}
    
        public synchronized void mark(int readlimit) {}
     
        public synchronized void reset() throws IOException {}
    
        public synchronized void close() throws IOException {}
    }

       查看源码,你会发现,这个装饰类提供了额外的方法unread(),这就意味着PushbackInputStream是一个半透明的装饰类。换言 之,它破坏了理想的装饰模式的要求。如果客户端持有一个类型为InputStream对象的引用in的话,那么如果in的真实类型是 PushbackInputStream的话,只要客户端不需要使用unread()方法,那么客户端一般没有问题。但是如果客户端必须使用这个方法,就 必须进行向下类型转换。将in的类型转换成为PushbackInputStream之后才可能调用这个方法。但是,这个类型转换意味着客户端必须知道它 拿到的引用是指向一个类型为PushbackInputStream的对象。这就破坏了使用装饰模式的原始用意。

      现实世界与理论总归是有一段差距的。纯粹的装饰模式在真实的系统中很难找到。一般所遇到的,都是这种半透明的装饰模式。


      下面是使用I/O流读取文件内容的简单操作示例。

    public class IOTest {
    
        public static void main(String[] args) throws IOException {
            // 流式读取文件
            DataInputStream dis = null;
            try{
                dis = new DataInputStream(
                        new BufferedInputStream(
                                new FileInputStream("test.txt")
                        )
                );
                //读取文件内容
                byte[] bs = new byte[dis.available()];
                dis.read(bs);
                String content = new String(bs);
                System.out.println(content);
            }finally{
                dis.close();
            }
        }
    
    }

      观察上面的代码,会发现最里层是一个FileInputStream对象,然后把它传递给一个BufferedInputStream对象,经过BufferedInputStream处理,再把处理后的对象传递给了DataInputStream对象进行处理,这个过程其实就是装饰器的组装过程,FileInputStream对象相当于原始的被装饰的对象,而BufferedInputStream对象和DataInputStream对象则相当于装饰器。

  • 相关阅读:
    Jmeter简单教程
    SpringMVC @RequestBody请求参数在postman中的请求
    maven多环境部署
    idea中项目文件颜色含义
    本地Consumer和Producer无法使用远程Kafka服务器的处理办法
    CentOS7 64位下MySQL5.7安装与配置(YUM)
    git学习笔记
    Nginx的启动、重启、关闭命令
    Mysql update 错误
    spring框架源码编译
  • 原文地址:https://www.cnblogs.com/bigwolf/p/4832575.html
Copyright © 2020-2023  润新知