• 代理模式和装饰者模式


    代理模式和装饰器模式很像,这里用【到咖啡馆喝咖啡】作例子来讲解。

    基础实现

    定义一个咖啡的接口。

    复制代码
    public interface Coffee {
        /**
         * 打印当前咖啡里有什么
         */
        void printMaterial();
    }
    复制代码

    定义一个苦咖啡的实现。

    复制代码
    public class BitterCoffee implements Coffee {
        @Override
        public void printMaterial() {
            System.out.println("咖啡");
        }
    }
    复制代码

    定义一个默认的点咖啡逻辑。

    @Test
    public void orderCoffee {
        Coffee coffee = new BitterCoffee();
        coffee.printMaterial(); // 咖啡
    }

    装饰器模式

    你喝了一口咖啡,觉得有点苦,于是你就想加点糖。

    定义一个咖啡装饰器(加糖)。

    复制代码
    public class CoffeeDecorator implements Coffee {
        /**
         * 持有一个咖啡对象
         */
        private final Coffee coffee;
    
        public CoffeeDecorator(Coffee coffee) {
            this.coffee = coffee;
        }
    
        @Override
        public void printMaterial() {
            System.out.println("糖");
            this.coffee.printMaterial();
        }
    }
    复制代码

    定义一个咖啡加糖的应用逻辑。

    复制代码
    @Test
    public void addSugerIntoCoffee {
        Coffee coffee = new BitterCoffee(); // 点了一杯苦咖啡
        coffee = new SugarDecorator(coffee); // 给咖啡加了点糖
        coffee.printMaterial(); // 糖 咖啡
    }
    复制代码

    装饰器适用场景:我有一个对象,但是这个对象的功能不能使我满意(咖啡太苦了),我就拿装饰器给他装饰一下(给咖啡加糖)。

    代理模式(静态代理)

    约好的朋友来了,要给她点一杯咖啡,你知道咖啡很苦,决定直接点一杯加了糖的咖啡给她。

    定义一个加糖咖啡的类。

    复制代码
    public class CoffeeProxy implements Coffee {
        private final Coffee coffee;
    
        public CoffeeProxy() {
            this.coffee = new BitterCoffee();
        }
    
        @Override
        public void printMaterial() {
            System.out.println("糖");
            this.coffee.printMaterial();
        }
    }
    复制代码

    然后定义一个点加糖咖啡的逻辑。

    @Test
    public void addSugerIntoCoffee {
        Coffee coffee = new CoffeeProxy();
        coffee.printMaterial(); // 糖 咖啡
    }

    装饰器和代理模式的区别

    对装饰器模式来说,装饰者(Decorator)和被装饰者(Decoratee)都实现一个接口。对代理模式来说,代理类(Proxy Class)和真实处理的类(Real Class)都实现同一个接口。此外,不论我们使用哪一个模式,都可以很容易地在真实对象的方法前面或者后面加上自定义的方法。

    在上面的例子中,装饰器模式是使用的调用者从外部传入的被装饰对象(coffee),调用者只想要你把他给你的对象装饰(加强)一下。而代理模式使用的是代理对象在自己的构造方法里面new的一个被代理的对象,不是调用者传入的。调用者不知道你找了其他人,他也不关心这些事,只要你把事情做对了即可。

    装饰器模式关注于在一个对象上动态地添加方法,而代理模式关注于控制对对象的访问。换句话说,用代理模式,代理类可以对它的客户隐藏一个对象的具体信息。因此当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例;当使用装饰器模式的时候,我们通常的做法是将原始对象作为一个参数传给装饰器的构造器。

    装饰器模式和代理模式的使用场景不一样,比如IO流使用的是装饰者模式,可以层层增加功能。而代理模式则一般是用于增加特殊的功能,有些动态代理不支持多层嵌套。

    代理和装饰其实从另一个角度更容易去理解两个模式的区别:代理更多的是强调对对象的访问控制,比如说,访问A对象的查询功能时,访问B对象的更新功能时,访问C对象的删除功能时,都需要判断对象是否登陆,那么我需要将判断用户是否登陆的功能抽提出来,并对A对象、B对象和C对象进行代理,使访问它们时都需要去判断用户是否登陆,简单地说就是将某个控制访问权限应用到多个对象上;而装饰器更多的强调给对象加强功能,比如说要给只会唱歌的A对象添加跳舞功能,添加说唱功能等,简单地说就是将多个功能附加在一个对象上。

    所以,代理模式注重的是对对象的某一功能的流程把控和辅助,它可以控制对象做某些事,重心是为了借用对象的功能完成某一流程,而非对象功能如何。而装饰模式注重的是对对象功能的扩展,不关心外界如何调用,只注重对对象功能加强,装饰后还是对象本身。

    总结

    对于代理类,如何调用对象的某一功能是思考重点,而不需要兼顾对象的所有功能;对于装饰类,如何扩展对象的某一功能是思考重点,同时也需要兼顾对象的其他功能,因为再怎么装饰,本质也是对象本身,要担负起对象应有的职责,被装饰者的职责一旦增加,作为装饰类也需要有相应的扩展,必然会造成编码的负担。

    设计模式本身是为了提升代码的可扩展性,灵活应用即可,不必生搬硬套,非要分出个所以然来,装饰器模式和代理模式的区别也是如此。

    "我们提着过去,走向人群。"

  • 相关阅读:
    免费的视频、音频转文本
    Errors are values
    Codebase Refactoring (with help from Go)
    Golang中的坑二
    Cleaner, more elegant, and wrong(msdn blog)
    Cleaner, more elegant, and wrong(翻译)
    Cleaner, more elegant, and harder to recognize(翻译)
    vue控制父子组件渲染顺序
    computed 和 watch 组合使用,监听数据全局数据状态
    webstorm破解方法
  • 原文地址:https://www.cnblogs.com/gloryhope/p/11446646.html
Copyright © 2020-2023  润新知