zoukankan      html  css  js  c++  java
  • 代理模式(Proxy)

             代理模式定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。

    来源《大话设计模式》

         一:静态代理   扩展不方便,需要知道具体的目标类,下面例子实际就是母亲给儿子,儿子的eat方法之前或之后增加一些业务逻辑,但是母亲目前只能给儿子做饭,不能给儿子的爸爸做饭,这就是静态代理的局限之处,无法实现动态扩展。

    //人类
    public interface Person {
        void eat();
    }
    
    //儿子
    public class Son implements Person {
        @Override
        public void eat() {
            System.out.println("吃饭");
        }
    }
    
    //母亲
    public class Mother implements Person {
        private Person son;
    
        public Mother(Person son) {
            this.son = son;
        }
        @Override
        public void eat() {
            System.out.println("妈妈做饭");
            son.eat();
            System.out.println("妈妈洗碗");
        }
    }
    
    public class StaticProxyTest {
        //静态代理
        public static void main(String[] args) {
            Person person = new Mother(new Son());

    person.eat();
     } }

    结果:   

         

         二:动态代理  动态代理其实相比静态代理而言,而且在代理之前,目标类中的方法可以为未知的。动态代理实现方式一般都有两种:JDK动态代理和CGLib动态代理

         JDK动态代理

    接口:Subject.java

    public interface Subject {
        //干活
        void doThing();
    
    }

    真实对象:RealSubject.java

    public class RealSubject implements Subject {
    
        @Override
        public void doThing() {
            System.out.println("干活");
        }
    }

    代理对象生成:实现InvocationHandler接口

    public class MyInvocationHander implements InvocationHandler {
        private Subject sub;
        public Object getInstance(Subject target){
            this.sub = target;
            Object o = Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
            return o;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("before doThing");//前置行为
            method.invoke(sub,args);
            System.out.println("after doThing");//后置行为
            return proxy; 
    } }

    测试类:JdkDynamicProxyTest .java

    public class JdkDynamicProxyTest {
        //jdk动态代理测试
        public static void main(String[] args) {
            RealSubject subject = new RealSubject();
            Subject target = (Subject)new MyInvocationHander().getInstance(subject);
            target.doThing();
        }
    }

          CGLib动态代理:上面基于JDK的动态代理必须实现接口, CGLib动态代理没有这个限制,private或是final类修饰的方法,则不会被重写。

    接口:Engineer 

    public class Engineer {
        public void work() {
            System.out.println("工程师正在工作");
        }
    }

    CGLIB 代理类:CglibProxy

    public class CglibProxy implements MethodInterceptor {
        private Object target;
    
        public CglibProxy(Object target) {
            this.target = target;
        }
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            System.out.println("前置行为");
            Object result = method.invoke(target, objects);
            System.out.println("后置行为");
            return result;
        }
    
        public static Object getProxy(Object target) {
            Enhancer enhancer = new Enhancer();
            // 设置需要代理的对象
            enhancer.setSuperclass(target.getClass());
            // 设置代理人
            enhancer.setCallback(new CglibProxy(target));
            return enhancer.create();
        }
    }

    测试类:

    public class CglibMainTest {
        public static void main(String[] args) {
            // 生成 Cglib 代理类
            Engineer engineerProxy = (Engineer) CglibProxy.getProxy(new Engineer());
            // 调用相关方法
            engineerProxy.eat();
        }
    }

    总结:

             主要优点有:

    1. 代理模式在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
    2. 代理对象可以扩展目标对象的功能;
    3. 代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度;

             主要缺点是:

    1. 在客户端和目标对象之间增加一个代理对象,会造成请求处理速度变慢;
    2. 增加了系统的复杂度;
  • 相关阅读:
    NBOJv2 1022 短信篮球(种类并查集)
    POJ 1182 食物链(种类并查集)
    虚拟机下samba简单安装配置
    gcc5.1.0升级指南
    廖雪峰Java16函数式编程-2Stream-7其他操作
    廖雪峰Java16函数式编程-2Stream-6reduce
    廖雪峰Java16函数式编程-2Stream-5filter
    廖雪峰Java16函数式编程-2Stream-4map
    廖雪峰Java16函数式编程-2Stream-2创建Stream
    廖雪峰Java16函数式编程-2Stream-1Stream简介
  • 原文地址:https://www.cnblogs.com/dyg0826/p/11309043.html
Copyright © 2011-2022 走看看