zoukankan      html  css  js  c++  java
  • 学习设计模式

    学习设计模式 - 代理模式

    一丶定义

       代理模式为另一个对象提供替身或者占位符以控制对这个对象访问, 被代理的对象可以是远程的对象、创建开销大的对象、需要安全控制的对象

     

    二丶理解

       2.1) 当一个对象除了处理真正的业务逻辑之外, 还需要增加额外的处理,如事务,打印日志等等, 如果将这些额外逻辑放到原对象中,会造成职责不清晰.
              这时可以使用代理对象代理该对象, 代理对象实现额外逻辑, 真正的业务逻辑则委托给被代理对象处理.这样可以使得职责清晰.


         2.2) 为另一个对象提供一个替身或占位符以控制对这个对象的访问.这也是代理模式和装饰者模式之间的重要区别
              当一个对象是大对象或者消耗资源的对象, 为提高系统性能, 可以使用代理对象暂时替代该对象, 到真正需要的时候才生成该对象.
              当权限不够时,可以使用代理对象限制对该对象的访问.

     

     

    三丶静态代理

      

     

      a. 主题

    public interface Subject {
        void request();
    }

      b. 真实主题

    public class RealSubject implements Subject {
        @Override
        public void request() {
            System.out.println("真正业务逻辑...");
        }
    }

       c. 代理

    public class Proxy implements Subject {
    
        private Subject subject;
    
        public Proxy(Subject subject) {
            this.subject = subject;
        }
    
        @Override
        public void request() {
            System.out.println("增加事务...");
            subject.request();
        }
    }

      d. 场景类

    /**
     * 静态代理
     *
     *  缺点:
     *      相同的代理方法,却要写多个代理类
     * @author TimFruit
     * @date 19-5-25 下午10:15
     */
    public class Client {
    
        public static void main(String[] args) {
            Proxy proxy=new Proxy(new RealSubject());
            proxy.request();
    
            Proxy2 proxy2=new Proxy2(new RealSubject2());
            proxy2.request();
        }
    
    }

      运行结果为:

    增加事务...
    真正业务逻辑...
    增加事务...
    真正的业务处理2...

      还有类似的代码Proxy2没有贴出来, 完整代码可以点此查看

     

    四丶JDK动态代理

      由上面代码可知, 使用静态代理需要为每个"被代理的类", 实现代理类, 当代理类实现方法相同时, 将会产生很多繁琐重复的代码, 因此有了动态代理, 动态代理一般有两种常用的实现, 一种是jdk动态代理, 一种是cglib动态代理. 这里展示的是jdk动态代理.

     

    /**
     * 实现jdk自带的接口
     * 写一个较为通用的"切面"类
     * @author TimFruit
     * @date 19-5-26 上午10:57
     */
    public class ProxyInvocationHandler implements InvocationHandler {
    
        private Object target;
    
        public ProxyInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("增加事务...");
            return method.invoke(target, args);
        }
    }

      

      场景类:

    /**
     * JDK动态代理
     *  <p>
     *      好处是写一个较为通用的"切面"类就可以了, 动态生成对应的代理类, 减少代码量
     *
     * @author TimFruit
     * @date 19-5-26 上午11:00
     */
    public class Client {
        public static void main(String[] args) {
    
            RealSubject subject=new RealSubject();
            InvocationHandler proxyInvocationHandler=new ProxyInvocationHandler(subject);
            //动态生成代理类
            Subject subjectProxy= (Subject) Proxy.newProxyInstance(Client.class.getClassLoader(), new Class[]{Subject.class}, proxyInvocationHandler);
            subjectProxy.request();
    
    
    
            RealSubject2 subject2=new RealSubject2();
            InvocationHandler proxyInvocationHandler2=new ProxyInvocationHandler(subject2);
            // 动态生成代理类
            Subject2 subjectProxy2= (Subject2) Proxy.newProxyInstance(RealSubject2.class.getClassLoader(), new Class[]{Subject2.class}, proxyInvocationHandler2);
            subjectProxy2.request();
        }
    }

       运行结果为:

    增加事务...
    真正业务逻辑...
    增加事务...
    真正的业务处理2...

       完整代码点此查看

     

     

     学习资料:

      <Head First 设计模式>

      <设计模式之禅>

     

     

    人生没有彩排,每一天都是现场直播
  • 相关阅读:
    Dijkstra单源最短路模板
    Naming Company CodeForces
    Naming Company CodeForces
    CF
    CF
    Present CodeForces
    9绑定方法与非绑定方法
    pycharm设置连接
    8封装的意义和拓展性
    property特性
  • 原文地址:https://www.cnblogs.com/timfruit/p/11154804.html
Copyright © 2011-2022 走看看