美文网首页
设计模式学习-代理模式

设计模式学习-代理模式

作者: m1Ku | 来源:发表于2019-08-07 15:43 被阅读0次

    定义

    代理模式又称为委托模式,它可以为其他对象提供一种代理以控制对这个对象的访问。我们可以通过代理对象间接访问被代理对象,代理对象和被代理对象需要实现相同的接口。代理模式在生活中很常用,比如外卖员帮我们送餐,律师帮我们打官司,或者是银行大堂经理帮我们办业务,都是代理模式的实现。

    UML类图

    代理模式

    代理模式的角色

    • Subject

      抽象主题,代理类和被代理类都需要实现该接口。

    • ConcreteSubject

      委托类,实现了抽象主题接口。

    • ProxySubject

      代理类,也实现了抽象主题接口,并且在构造中传入了委托类对象,这样就可以调用委托类的方法。

    示例

    静态代理

    静态代理需要自行定义代理对象,这里以去银行办理业务为例,抽象出申请卡和注销卡操作为IBank接口。

    /**
     * 定义委托类和代理类共同的接口方法(接口或者抽象类)
     * 相当于是委托类和代理类行为的抽象
     */
    public interface IBank {
         void applyCard();
         void cancelCard();
    }
    

    定义委托类和代理类

    /**
     * 委托类,执行具体的业务逻辑方法
     */
    public class Man implements IBank {
        @Override
        public void applyCard() {
            System.out.println("客户填单,申请办卡");
        }
    
        @Override
        public void cancelCard() {
            System.out.println("客户填单,申请挂失");
        }
    }
    
    /**
     * 代理类,该类持有委托类的引用,在其实现的方法中调用委托类中
     * 相应的接口方法执行,起到代理的作用
     */
    public class BankManager implements IBank {
    
        private IBank man;
    
        /**
         * 构造方法中传入委托类
         * @param man
         */
        public BankManager(IBank man){
            this.man = man;
        }
    
        @Override
        public void applyCard() {
            System.out.println("银行经理,问询客户需求");
            //调用委托类对应的接口方法
            man.applyCard();
            System.out.println("欢送客户");
        }
    
        @Override
        public void cancelCard() {
            System.out.println("银行经理,问询客户需求");
            man.cancelCard();
            System.out.println("欢送客户");
        }
    }
    

    在客户端实例化委托类,并将其传入代理类,调用代理方法

    public class Client {
        public static void main(String []args){
            Man man = new Man();
            //将委托类传入代理类
            BankManager manager = new BankManager(man);
            //调用代理类的接口方法
            manager.applyCard();
            manager.cancelCard();
        }
    }
    

    动态代理

    相对于静态代理,动态代理在编码阶段不需要编写代理类,而是通过反射机制动态的生成代理者的对象的,Java提供了InvocationHandler接口,通过实现该接口可以完成动态代理,具体实现如下,还是代理Man对象。

       /**
         * 实现InvocationHandler接口,构造方法中传入委托类
         * invoke方法中调用委托类的方法
         */
        public static class BankInvocationHandler implements InvocationHandler{
            private Man man;
            public BankInvocationHandler(Man man){
                this.man = man;
            }
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("接待客户");
                Object object = method.invoke(man,args);
                System.out.println("欢送客户");
                return object;
            }
        }
    
    public class Client {
        public static void main(String[]args){
    
            Man man = new Man();
            //调用newProxyInstance方法获得代理类
            IBank proxy = (IBank) Proxy.newProxyInstance(
                    IBank.class.getClassLoader(),
                    new Class<?>[]{IBank.class},
                    new BankInvocationHandler(man)
            );
            //调用代理类的方法
            proxy.applyCard();
            proxy.cancelCard();
        }
    

    调用代理类的方法时,会执行到InvocationHandler的invoke方法,在这个方法中又调用了委托类对应的方法,可以添加我们自己的逻辑,这就完成了对Men对象的代理。

    Android源码中的代理模式

    Retrofit网络请求框架就是使用了动态代理的方式,代理了网络请求接口完成的网络请求。具体Retrofit源码分析看Android源码学习-Retrofit源码浅析

    相关文章

      网友评论

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

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