zoukankan      html  css  js  c++  java
  • 【设计模式】3.代理模式

    代理模式

    代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问。

    1.提高扩展性和复用性

    2.保护目标对象

    结构图:

     

    Subject:RealSubjectProxy的公共接口

    RealSubject:Proxy代理的真实实体

    Proxy:代理,与RealSubject实现同一接口,代理就可以代替真实实体。

    Java中的代理技术:JDKCGLIBJavaassistASM

    Spring中常用JDKCGLIB

    Mybatis中使用Javaassist

    场景:假如软件的研发过程中,程序员不能直接与客户对接,必须由产品经理与客户进行对接,从而研发部门根据客户的需求进行相应研发工作。这里产品经理和程序员都是研发部门的员工,具有相同的职责(产品研发)。产品经理就代理了程序员的具体工作,可以采用代理模式。

     例:

    1. 静态代理方式:

    public interface Staff {      // Subject
    
        void createWebAPP();      // 开发Web应用
    
        void createAndroidApp();  // 开发Android应用
    
    }
    public class Programmer implements Staff {  // RealSubject
    
        @Override
    
        public void createWebAPP() {
    
            System.out.println("Web应用开发");
    
        }
    
        @Override
    
        public void createAndroidApp() {
    
            System.out.println("Android应用开发");
    
        }
    
    }
    public class Manager implements Staff {       // Proxy
    
        Programmer programmer;
    
        @Override
    
        public void createWebAPP() {
    
            if (programmer == null) {
    
                programmer = new Programmer();
    
            }
    } @Override
    public void createAndroidApp() { if (programmer == null) { programmer = new Programmer(); } } }
    public class Test {
    
        public static void main(String[] args) {
    
            Manager manager = new Manager();  
    
            manager.createAndroidApp();  // 代理执行被代理的方法
    
            manager.createWebAPP();
    
        }
    
    }

    输出:

    Web应用开发
    Android应用开发

    2. 动态代理方式:

    1JDK动态代理

      底层使用反射,只能创建接口的代理。

    public interface Staff {      // Subject
    
        void createWebAPP();      // 开发Web应用
    
        void createAndroidApp();  // 开发Android应用
    
    }
    public class Programmer implements Staff {  // RealSubject
    
        @Override
    
        public void createWebAPP() {
    
            System.out.println("Web应用开发");
    
        }
    
        @Override
    
        public void createAndroidApp() {
    
            System.out.println("Android应用开发");
    
        }
    
    }
    public class DynamicProxyHandler implements InvocationHandler { // Proxy,代理类必须实现InvocationHandler接口
    
        Object  target;    // 被代理的对象,可以是任何对象(Object是任何类的父类)
    
        /**
    
         * 1. 建立代理对象与被代理对象之间的关系
    
         * @param target 被代理对象
    
         * @return 被代理对象
    
         */
    
        public Object bind(Object target) {
    
            this.target = target;
    
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    
            // 三个参数:target的类加载器;把生成的动态代理的对象挂在哪些接口下,这里是挂在target实现的接口下;实现方法逻辑的代理类
    
        }
    
        /**
    
         *  2. 实现代理逻辑的方法,调用被代理对象的任何方法,此方法都会执行
         *   @param proxy 代理对象(bind方法生成的)
    
         *   @param method 当前调度的方法
    
         *   @param args 当前方法参数
    
         *   @return 代理结果返回
    
         *   @throws Throwable 异常
    
         */
    
        @Override
    
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
            Object result = method.invoke(target, args);
    
            return result;
    
        }
    
    }
    public class Test {
    
        public static void main(String[] args) {
    
            DynamicProxyHandler proxyHandler = new DynamicProxyHandler();
            // 绑定具体的代理对象,返回给其接口的引用
            Staff proxy = (Staff) proxyHandler.bind(new Programmer()); 
    
          proxy.createWebAPP(); // 代理执行被代理的方法  
        proxy.createAndroidApp();
        
      }


    }

    输出:

    Web应用开发
    Android应用开发

    (2)CGLIB动态代理

      不需要提供接口,只要一个非抽象类(被代理对象)。底层提供使用字节码处理框架ASM,创建类和接口的代理。

    依赖:

    <dependency>
    
         <groupId>cglib</groupId>
    
         <artifactId>cglib</artifactId>
    
         <version>3.3.0</version>
    
    </dependency>
    public class Programmer {        // RealSubject
    
        public void createWebAPP() {
    
            System.out.println("Web应用开发");
    
        }
    
        public void createAndroidApp() {
    
            System.out.println("Android应用开发");
    } }
    public class CglibProxy implements MethodInterceptor {   // 必须实现MethodInterceptor
    
        /**
    
         * 生成CGLIB代理对象
    
         * @param cls Class 类
    
         * @return Class 类的CGLIB代理对象
    
         */
    
        public Object getProxy(Class cls) {
    
            // CGLIB 增强对象
    
            Enhancer enhancer = new Enhancer();
    
            // 设置增强类型
    
            enhancer.setSuperclass(cls);
    
            // 定义代理逻辑对象为当前对象,要求当前对象实现MethodInterceptor方法
    
            enhancer.setCallback(this);
    
            // 生成并返回对象
    
            return enhancer.create();
    
        }
    
        /**
    
         * 代理逻辑方法
    
         * @param o 代理对象
    
         * @param method 方法
    
         * @param objects 方法参数
    
         * @param methodProxy 方法代理
    
         * @return 代理逻辑返回
    
         * @throws Throwable 异常
    
         */
    
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
            // CGLIB 反射调用的真实对象方法
    
            Object result = methodProxy.invokeSuper(o,objects);
    
            return result;
    
        }
    
    }
    public class Test {
    
        public static void main(String[] args) {
    
            CglibProxy cp = new CglibProxy();
    
            Programmer pg = (Programmer)cp.getProxy(Programmer.class);
    
            pg.createWebAPP();
    
            pg.createAndroidApp();
    
        }
    }
  • 相关阅读:
    android listview去掉分割线
    svn 上传 过滤
    PPPOE 模拟环境搭建
    Android笔记之网络-基本了解
    ios多线程操作(五)—— GCD串行队列与并发队列
    UVa 679
    android中更改spinner、AutoCompleteTextView切割线的颜色
    Cocos2d-x中触摸事件
    全然符合package.json在CommonJS中的规范
    Hibernate实体对象继承策略
  • 原文地址:https://www.cnblogs.com/jiazhongxin/p/12802712.html
Copyright © 2011-2022 走看看