漫谈设计模式之:代理模式

我的新书《Android App开发入门与实战》已于2020年8月由人民邮电出版社出版,欢迎购买。点击进入详情

简介

代理,是一个中间者的角色,它屏蔽了访问方和委托方之间的直接接触。
也就是说访问方不直接调用委托方的这个对象,而是通过实例化一个跟委托方有同样接口的代理方,通过这个代理方来完成对委托方的调用。访问方只和代理方打交道,这个代理方有点像掮客的角色。现实生活中代理好比房产中介。
什么时候需要用到代理模式呢?

  1. 访问方不想和委托方直接接触,或者直接接触有困难。
  2. 访问方对委托方的访问需要增加额外处理,比如访问前和访问后都做一些处理。这种情况下我们不能直接对委托方的方法进行修改,这样同样违反了开闭原则

代理模式有两类:静态代理和动态代理,下面我们分别通过代码详细说明。

静态代理

静态代理主要是代理类需要每次都要手工创建。

private interface ICar {
        void move();
    }

    private class Benz implements ICar {

        @Override
        public void move() {
            ToastUtil.showToast("Benz move");
        }
    }

    //代理类
    private class BenzProxy implements ICar {
        private Benz benz;

        public BenzProxy() {
            benz = new Benz();
        }

        @Override
        public void move() {
            //做一些前置工作,比如检查车辆的状况
            //before();
            benz.move();
            //做一些后置工作,比如检查结果
            //after();
        }
    }
    //调用
    BenzProxy proxy1 = new BenzProxy();
    proxy1.move();

动态代理

动态代理的代理类可以根据委托类自动生成,而不需要像静态代理那样通过手工创建。代理类的代码不是在java代码中定义的,而是在运行的时候动态生成的。

	//动态代理类
    public class CarHandler implements InvocationHandler {

        //目标类的引用
        private Object target;

        public CarHandler(Object target) {
            this.target = target;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //做一些前置工作,比如检查车辆的状况
            before();

            //调用被代理类的方法
            Object result = method.invoke(target, args);

            //做一些后置工作,比如检查结果
            //after();
            return result;
        }

        private void before() {
            ToastUtil.showToast("before Benz move");
        }
    }
	//调用方
	ICar car1 = new Benz();
	InvocationHandler handler = new CarHandler(car1);
	ICar proxy2 = (ICar) Proxy.newProxyInstance(ICar.class.getClassLoader(), new Class[]{ICar.class}, handler);
	proxy2.move();

动态代理+简单工厂

接着上面动态代理调用方的使用方式,我们可以通过工厂模式,加上泛型,优化一下动态代理的生成和调用。

public class ProxyFactory<T> {

        private T client;//目标对象
        private IBefore before; // 前置增强
        private IAfter after; // 后置增强

        @SuppressWarnings("unchecked")
        public <T> T createProxy() {
            ClassLoader loader = client.getClass().getClassLoader();
            Class[] interfaces = client.getClass().getInterfaces();
            InvocationHandler h = new InvocationHandler() {
                public Object invoke(Object proxy, Method method, Object[] args)
                        throws Throwable {
                    if("getName".equals(method.getName())){
                        //可根据name值过滤方法
                    }
                    //前置
                    if (before != null) {
                        before.doBefore();
                    }
                    Object result = method.invoke(client, args);//执行目标对象的目标方法
                    if (after != null) {
                        after.doAfter();
                    }
                    return result;
                }
            };
            return (T) Proxy.newProxyInstance(loader, interfaces, h);
        }

        public void setClient(T client) {
            this.client = client;
        }

        public void setBefore(IBefore before) {
            this.before = before;
        }

        public void setAfter(IAfter after) {
            this.after = after;
        }
    }

    public interface IBefore {
        void doBefore();
    }

    public interface IAfter {
        void doAfter();
    }
    //调用
    ProxyFactory factory = new ProxyFactory();//创建工厂
    factory.setBefore(new IBefore() {
        @Override
        public void doBefore() {
            System.out.println("doBefore.");
        }
    });
    factory.setClient(new Benz());
    factory.setAfter(new IAfter() {
        @Override
        public void doAfter() {
            System.out.println("doAfter.");
        }
    });
    ICar car2 = (ICar) factory.createProxy();
    car2.move();

动态代理拓展:AOP

Aspect-Oriented Programming,面向切面编程。
AOP的实现就是用了动态代理。
简单来说,AOP就是能够动态地将代码切入到指定的位置,在指定位置上实现编程,从而达到动态改变原有代码的行为
上面的IBefore和IAfter接口实际上就是实现了简单的AOP,比如在invoke具体方法之前和之后,我们可以插入一些操作。

Proxy.newProxyInstance

public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

loader: 委托类的classLoader;
interfaces: 代理类需要实现的接口,这个接口同委托类的接口;
h: 调用处理器,只有一个invoke方法,调用委托类的任何方法都是通过它的invoke方法。

git地址

https://github.com/ddnosh/AndroidQuick

weixin063传染病防控宣传微信小程序系统的设计与实现+springboot后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值