zoukankan      html  css  js  c++  java
  • 装饰器模式-Decerator

    一、定义

    装饰器模式又叫做包装模式(Wrapper)。装饰器模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

    在以下情况下应该使用装饰器模式:

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

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

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

    二、类图

    装饰器模式中的角色有:

    • 抽象组件角色:给出一个抽象接口,一规范准备接收附加责任的对象
    • 具体组件角色:定义一个将要接收附加责任的类
    • 装饰角色:持有一个组件对象的实例,并定义一个一个与抽象组件接口一致的接口。
    • 具体装饰角色:负责给组件对象"贴上去"附加的责任。

    将类图转换为代码,如下所示。

    /**
     * 装饰者通过对被装饰者进行装饰,从而使得自己拥有的加强的行为
     * 
     * @author lp
     *
     */
    public class Client {
    
        public static void main(String[] args) {
            // 被装饰者
            Component component = new ConcreteComponent();
            // 装饰者
            Decorator decorator = new ConcreteDecorator(component);
    
            // 被装饰者的行为
            component.operation();
            // 装饰者既具有被装饰者的行为,也有增加的行为。即对被装饰者进行了装饰。
            decorator.operation();
            decorator.addedBehavior();
        }
    
    }
    
    /**
     * 抽象的被装饰者
     */
    interface Component {
        void operation();
    }
    
    /**
     * 具体的被装饰者
     */
    class ConcreteComponent implements Component{
    
        @Override
        public void operation() {
            System.out.println("被装饰者的操作");
        }
    
    }
    
    /**
     * 抽象的装饰者
     */
    interface Decorator extends Component{
        /**
         * 增加的方法
         */
        void addedBehavior();
    }
    
    /**
     * 具体的装饰者
     */
    public class ConcreteDecorator implements Decorator {
    
        // 持有被装饰者的引用
        private Component decoratedComponent;
    
        // 通过构造器将被装饰者传进来
        public ConcreteDecorator(Component decoratedComponent) {
            this.decoratedComponent = decoratedComponent;
        }
    
        @Override
        public void operation() {
            System.out.println("decorated operation!");
            decoratedComponent.operation();
        }
        
        /**
         * 添加的功能
         */
        @Override
        public void addedBehavior() {
            System.out.println("addedBehaviour!");
        }
    
    }

    应该指出:

    • 装饰类中,有一个私有的属性component,其数据类型是组件(Component)
    • 该装饰器类实现了Component接口
    • 接口的实现方法也值得注意,每一个实现的方法都委派给父类,但并不单纯的委派,而是有功能的增强。

    三、JDK中的装饰器模式

    JDK中的部分流的实现就使用了装饰器模式,比如BufferedInputStream对InputStream进行了装饰,BufferedReader对Reader进行了装饰,对应的OutputStream和Write也分别被BufferedOutputStream和BufferedWriter装饰了。

     

    下面以BufferedInputStream为例,来分析一下装饰者模式。

    /*抽象组件角色*/
    public abstract class InputStream implements Closeable {
        public abstract int read() throws IOException;
    }
    
    /*具体组件角色*/
    public class FileInputStream extends InputStream{
        public int read() throws IOException {
            Object traceContext = IoTrace.fileReadBegin(path);
            int b = 0;
            try {
                b = read0();
            } finally {
                IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1);
            }
            return b;
        }
    }
    
    /*抽象装饰器角色*/
    public class FilterInputStream extends InputStream {
        
        protected volatile InputStream in;
    
        protected FilterInputStream(InputStream in) {
            this.in = in;
        }
    
        public int read() throws IOException {
            return in.read();
        }
    
        public int read(byte b[], int off, int len) throws IOException {
            return in.read(b, off, len);
        }
    
    }
    
    /*具体装饰器角色*/
    public class BufferedInputStream extends FilterInputStream {
        
        protected volatile byte buf[];
        
        public BufferedInputStream(InputStream in){
            this(in, defaultBufferSize);
        }
    
        public synchronized int read() throws IOException {
            if (pos >= count) {
                fill();
                if (pos >= count)
                    return -1;
            }
            return getBufIfOpen()[pos++] & 0xff;
        }    
        
    }

    BufferedInputStream是继承自FilterInputStream的具体的装饰器类,该类提供一个内存的缓冲区来保存输入流中的数据。这样就带有缓冲功能,提高文件读入的效率。

    所以,我们通常以这样的形式来使用它们

    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
     ……更多设计模式的内容,可以访问Refactoring.Guru
  • 相关阅读:
    Vue 项目启动抛出 Error/ No PostCSS Config found in
    js sort排序
    layui table合计但是未计算的解决
    vue项目echarts画布删除历史数据重新渲染数据
    layui 数据返回但是table表格未渲染出来的问题
    Spring Boot实践——AOP实现
    IntelliJ IDEA—IDEA2018.1激活方式
    Spring Boot实践——统一异常处理
    Spring Boot实践——Filter实现
    Spring Boot实践——三种拦截器的创建
  • 原文地址:https://www.cnblogs.com/rouqinglangzi/p/6994229.html
Copyright © 2011-2022 走看看