zoukankan      html  css  js  c++  java
  • 装饰模式VS代理模式

    装饰模式VS代理模式

    个人理解

    代理模式:我想做,但不能做,我需要有一个能干的人来帮我做
    装饰模式:我想做,但不能做,我需要各类特长的人来帮我做,但是我有时需要很多人来帮我做,有时又只需要一个人做。
    区别:Proxy模式需要的是一个能人,而Decorator模式需要的是一个团队

    代理模式

    在这里插入图片描述

    public interface Greeting {
        void sayHello(String name);
    }
    
    public class GreetingImpl implements Greeting {
        @Override
        public void sayHello(String name) {
            System.out.println("hello: " + name);
        }
    }
    
    /**
     * 只需要包装GreetingProxy与GreetingImpl实现同一个接口Greeting,
     * 并通过构造方法将GreetingImpl传入GreetingProxy中。那么,
     * GreetingProxy 就可以完全拥有 GreetingImpl 了。可以在帮它做正事儿之前,
     * 先干点别的事情,比如这里的 before() 方法。想干点什么就干点什么,只要您喜欢,它就喜欢。
     */
    public class GreetingProxy implements Greeting {
        
        private GreetingImpl greeting;
        
        public GreetingProxy(GreetingImpl greeting) {
            this.greeting = greeting;
        }
        @Override
        public void sayHello(String name) {
            before();
            greeting.sayHello(name);
        }
        private void before() {
            System.out.println("before");
        }
    }
    
    public class ClientProxy {
        public static void main(String[] args) {
            Greeting greeting = new GreetingProxy(new GreetingImpl());
            greeting.sayHello("chen");
        }
    }
    

    问题:如果用户现在又来了一个需求:在完成sayHello()之后再需要插入一个数据库?
    好的,此时最简单的方法就是给GreetingProxy中增加一个after()方法,再after()方法中完成插入数据库的操作。
    那如果此时又改需求,在插入数据库之后,再添加日志。
    添加日志之后还需要一些其他的?
    这样的话,把所有功能都放在Proxy这个类中是不明智的,同时这也违反了“开闭原则”
    此时,我们可以考虑使用Decorator模式,让日志的,数据库的,before的,after的等都独自拥有自己的功能。(此时不再是需要一个人,而是需要一个团队,团队中每个人都有自己的功能,我可以随意搭配)

    装饰模式

    在这里插入图片描述

    /**
     * 这就是一个非常纯净的装饰器,没有任何的增强逻辑,只是简单的通过构造方法传入Greeting对象,
     * 然后调用传入对象的sayHello()方法一样
     * 相当于I/O中的FilterInputSream
     */
    public class GreetingDecorator implements Greeting {
    
        private Greeting greeting;
    
        public GreetingDecorator(Greeting greeting) {
            this.greeting = greeting;
        }
    
        @Override
        public void sayHello(String name) {
        	//相当于调用I/O中FileInputSream.read()中的方法
            greeting.sayHello(name);
        }
    }
    
    /**
     * 注意:一定是继承GreetingDecorator并不是Greeting,需要继承装饰器,成为一个具体的装饰器
     * 相当于I/O中的BufferedInputStream
     */
    public class GreetingBefore extends GreetingDecorator {
    
        public GreetingBefore(Greeting greeting) {
            super(greeting);
        }
    
        @Override
        public void sayHello(String name) {
            before();
            //调用的真正的sayHello方法是构造的时候传递过来的对象的sayHello()
            super.sayHello(name);
        }
    
        private void before() {
            System.out.println("before");
        }
    }
    
    public class GreetingAfter extends GreetingDecorator {
    
        public GreetingAfter(Greeting greeting) {
            super(greeting);
        }
    
        private void after() {
            System.out.println("after");
        }
    
        @Override
        public void sayHello(String name) {
            super.sayHello(name);
            after();
        }
    }
    
    
    public class ClientDecorator {
        public static void main(String[] args) {
        	//这里就可以任意的组合了
            Greeting greeting = new GreetingAfter(new GreetingBefore(new GreetingImpl()));
            greeting.sayHello("chen");
        }
    }
    

    总结

    代理模式和装饰模式都是对类的包装,在不改变类自身的情况下,为类添加特定的功能
    所以若对于功能比较单一,可考虑使用Proxy模式,但对于功能较多,且需要动态拓展的情况下,还是适合尝试使用Decorator模式

  • 相关阅读:
    分区助手怎么调整磁盘分区的大小
    3dsmax2014的下载、安装与注册激活教程详解
    U深度U盘启动盘制作工具怎么用?U深度U盘启动盘制作工具使用教学
    CAD出现向程序发送命令时出现问题提示解决方法分享
    TeamViewer——可以实现在手机上随时远程控制你的电脑
    CPU-Z五大主要功能及使用方法初步了解
    vs中更改项目名称注意事项
    Oracle 存储过程例子返回记录集
    oracle 调用包体的函数并返回return值
    oracle 中更新update不成功的原因
  • 原文地址:https://www.cnblogs.com/liuligang/p/10543200.html
Copyright © 2011-2022 走看看