设计模式-代理模式

作者: breezedancer | 来源:发表于2016-11-03 17:13 被阅读489次

    代理模式:给某个对象提供代理对象,由代理对象控制原来对象的引用。一般情况在客户端和原对象之间不好沟通的时候,有代理对象来介于二者之间,完成沟通工作;一旦一个对象被代理对象管理,代理对象就可能对原来对象执行方法前后进行拦截处理。

    先来看下类图:


    • 抽象主题:声明一个接口,为真实主题和代理主题都要实现的
    • 代理主题:内部包含真实主题的引用,可以在如何时候对真实主题进行方法调用,他与真实主题有相同的接口,也就可以伪装自己,貌似自己也可以做与真实主题同样的事件。他控制真实对象,在需要真实对象出现的时候,就把他创建出来,真实主题就相当于傀儡;当然代理一般也会增加或修改真实主题的功能。
    • 真实主题:被代理,傀儡

    演示下静态代理
    首先给出抽象主题

    public interface Subject {
    
        public void method();
    }
    

    接着给出具体主题

    public class RealSubject implements Subject{
    
        @Override
        public void method() {
            System.out.println("我是真实主题");
        }
    
    }
    
    

    最后代理出现:

    public class ProxySubject implements Subject {
    
        private Subject subject;
        
        public ProxySubject() {
        }
        
        @Override
        public void method() {
            if(subject==null){
                subject=new RealSubject();
            }
            preMethod();
            subject.method();
            postMethod();
        }
    
        private void postMethod() {
            System.out.println("代理人在执行前搞点事");
        }
    
        private void preMethod() {
            System.out.println("代理人在执行后搞点事");
        }
    
    }
    

    使用客户端程序跑一次试试

    public class Client {
    
        public static void main(String[] args) {
            Subject subject=new ProxySubject();
            subject.method();
        }
    
    }
    

    以上属于静态代理,比较简单。与之对应的是动态代理,在运行时间内创建代理对象,JDK提供了 Proxy 和InvokationHandler
    来处理
    首先构造动态代理类

    public class DynamicProxy implements InvocationHandler{
    
        private Object proxied;   
        
        public DynamicProxy(Object proxied) {
            this.proxied=proxied;
        }
        
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            before();
            Object instance=method.invoke(proxied, args);
            after();
            return instance;
        }
    
        public void before(){
            System.out.println("第一步");
        }
        
        public void after(){
            System.out.println("第二步");
        }
    }
    

    客户端调用如下

    public class DynamicClient {
    
        public static void main(String[] args) {
            Subject real = new RealSubject();   
            Subject proxySubject = (Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(), 
             new Class[]{Subject.class}, 
             new DynamicProxy(real));
            proxySubject.method();
    
        }
    
    }
    
    

    动态代理创建对象过程可分为以下四个步骤:
    1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);
    2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
    Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
    3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
    Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
    4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
    Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
    为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。
    生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))

    相关文章

      网友评论

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

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