美文网首页
【设计模式】- 代理模式

【设计模式】- 代理模式

作者: lconcise | 来源:发表于2019-03-12 09:30 被阅读0次

    代理模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象。
    这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能。

    这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法。

    代理模式的关键点是:代理对象与目标对象,代理对象是对目标对象的扩展,并会调用目标对象

    静态代理 Demo

    /**
     * 接口
     */
    public interface Count {
    
        void queryCount();
    
        void updateCount();
    }
    
    /**
     * 接口实现,目标对象
     */
    public class CountImpl implements Count {
    
        @Override
        public void queryCount() {
            System.out.println("查看账户。。。");
        }
    
        @Override
        public void updateCount() {
            System.out.println("修改账户。。。");
        }
    }
    
    /**
     * 代理对象,静态代理
     */
    public class CountProxy implements Count {
    
        // 接受保存目标对象
        private Count count;
    
        public CountProxy(Count count) {
            this.count = count;
        }
    
        @Override
        public void queryCount() {
            System.out.println("查询账户预处理。。。");
            count.queryCount();
            System.out.println("查询账户预之后。。。");
        }
    
        @Override
        public void updateCount() {
            System.out.println("修改账户预处理。。。");
            count.updateCount();
            System.out.println("修改账户预之后。。。");
        }
    }
    
    /**
     * 测试类
     */
    public class ProxyTest {
    
        public static void main(String[] args) {
            // 目标对象
            Count count = new CountImpl();
            // 代理对象,把目标对象传给代理对象,建立代理关系
            CountProxy proxy = new CountProxy(count);
            // 执行的是代理的方法
            proxy.queryCount();
            proxy.updateCount();
        }
    }
    

    静态代理:可以做到在不修改目标对象的功能前提下,对目标功能扩展。
    缺点
    因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多,同时,一旦接口增加方法,目标对象与代理对象都要维护。
    如何解决静态代理中的缺点呢?答案是可以使用动态代理方式

    两种常用的动态代理

    1. 基于接口的动态代理
      • 提供者 JDK
      • 使用JDK官方的Proxy类创建代理对象
      • 注意:代理的目标对象必须实现接口
    2. 基于类的动态代理
      • 提供者 第三方CGLib
      • 使用CGLib的Enhancer类创建代理对象

    动态代理(JDK实现)Demo

    /**
     * 接口
     */
    public interface Count {
    
        void queryCount();
    
        void updateCount();
    }
    
    /**
     * 接口实现,目标对象
     */
    public class CountImpl implements Count {
    
        @Override
        public void queryCount() {
            System.out.println("查看账户。。。");
        }
    
        @Override
        public void updateCount() {
            System.out.println("修改账户。。。");
        }
    }
    
    /**
     * 动态代理
     */
    public class DynamicProxy implements InvocationHandler {
    
        // 维护一个目标对象
        private Object object;
    
        public DynamicProxy(Object object) {
            this.object = object;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("操作前预处理");
            Object result = method.invoke(object, args);
            System.out.println("操作后后处理");
            return result;
        }
    }
    
    /**
     * 测试类
     */
    public class DynamicProxyTest {
    
        public static void main(String[] args) {
            // 目标对象
            Count count = new CountImpl();
            // 生产代理对象
            Count proxyInstance = (Count) Proxy.newProxyInstance(Count.class.getClassLoader(), new Class[]{Count.class}, new DynamicProxy(count));
            proxyInstance.queryCount();
            proxyInstance.updateCount();
        }
    }
    

    动态代理(CGLib实现)Demo

    /**
     * 目标对象,没有实现任何接口
     */
    public class Count {
    
        public void queryCount() {
            System.out.println("查看账户。。。");
        }
    
        public void updateCount() {
            System.out.println("修改账户。。。");
        }
    }
    
    /**
     * Cglib子类代理工厂
     */
    public class CglibProxy implements MethodInterceptor {
    
        private Object object;
    
        public Object getInstance(Object object) {
            this.object = object;
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(this.object.getClass());
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("操作前预处理");
            methodProxy.invokeSuper(o, objects);
            System.out.println("操作后预处理");
            return null;
        }
    }
    
    /**
     * 测试类
     */
    public class CglibProxyTest {
    
        public static void main(String[] args) {
            Count count = new Count();
            CglibProxy cglibProxy = new CglibProxy();
            Count instance = (Count) cglibProxy.getInstance(count);
            instance.queryCount();
            instance.updateCount();
        }
    }
    

    在Spring的AOP编程中:
    如果加入容器的目标对象有实现接口,用JDK代理
    如果目标对象没有实现接口,用CGLib代理

    相关文章

      网友评论

          本文标题:【设计模式】- 代理模式

          本文链接:https://www.haomeiwen.com/subject/rjpxpqtx.html