设计模式之代理模式

这是我参与更文挑战的第2天,活动详情查看: 更文挑战

代理模式的使用

在委托类和客户之间添加一层代理类,通过代理类来代理委托类的实现。简单来说就是生产厂家和消费者之间的商家代理。消费者从商家代理那边买到产品,消费者不用关心生产厂家的情况,而商家代理从生产厂家获取产品,生产厂家不用关心产品的销售。代理类在其中的优点在于:

  1. 隐藏委托类的实现。
  2. 委托类和和客户之间实现解耦。在不修改委托类的情况下,通过代理类可以做一些额外的操作。

静态代理

静态代理的原理在于手动实现一个代理类,如下面的ProxyHttp类,内部持有一个DelegateHttp委托类,通过调用代理类的方法来间接实现委托类。

    interface HttpService {

        void http(String msg,int target);
    }

    /**
     * 委托类 ,实现HttpService接口
     */
    static class DelegateHttp implements HttpService{

        @Override
        public void http(String msg, int target) {
            System.out.println("delegate msg="+msg+" target="+target);
        }
    }
    
    /**
     * 静态代理类 
     */
    private static class ProxyHttp {
        private DelegateHttp delegateHttp;

        public ProxyHttp(DelegateHttp o) {
            this.delegateHttp = o;
        }

        public void http(String msg, int target) {
            delegateHttp.http(msg, target);
        }
    }
复制代码

静态代理的缺点在于:代理类在编译期实现,如果存在多个委托类,或者需要对委托类做一些额外的操作,就需要修改或者增加代理类。如果说修改的地方过多,改动过大的话,有些得不偿失。

动态代理

动态代理在运行期通过反射生成对应的代理类。动态代理中使用到了InvocationHandler接口,实现该接口和对应的invoke方法来调用委托类的实现。

    public static void main(String[] args) {

        DelegateHttp delegateHttp = new DelegateHttp();
        getProxy(delegateHttp).http("this is proxy", 10000);
    }
    
/**
     * 代理类
     */
    private static HttpService getProxy(HttpService delegateHttp) {
        HttpInvocationHandler invocationHandler = new HttpInvocationHandler(delegateHttp);
        return (HttpService) Proxy.newProxyInstance(HttpService.class.getClassLoader(),
                new Class[]{HttpService.class}, invocationHandler);
    }

    /**
     * 中介类
     */
    static class HttpInvocationHandler implements InvocationHandler {

        private Object delegate;

        public HttpInvocationHandler(Object delegate) {
            this.delegate = delegate;
        }

        @Override
        public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
            System.out.println("dynamic proxy start------");
            Object result = method.invoke(delegate, objects);
            System.out.println("dynamic proxy end------");
            return result;
        }
    }

复制代码

InvocationHandler相当于中介类,代理类调用中介类,而中介类中持有委托类对象引用。当调用委托类的方法时,会执行到InvocationHandlerinvoke方法,我们可以在invoke方法中做一些额外的操作,比如添加日志等。

敲黑板

代理模式是对委托类的实现进行代理,达到实现的扩展和解耦。注意啊动态代理只针对接口,如果是普通的类的话,会报错的。最后千万不要理解为是对接口的实现啊,我以前一直是这样认为的。

最后

动态代理的原理在于动态的生成一个$Proxy0代理类,该类继承自Proxy并实现需要代理的接口。加入下面这句代码,可以查看并生成对应的代理类:

System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享