设计模式之——代理设计模式

来源:互联网 发布:2014网络春晚 白客 编辑:程序博客网 时间:2024/06/03 17:03

代理模式说白了就是中介,A要完成C,并不是直接去完成而是委托中介B去完成,B就是连接A与C的代理,B可以完全替代A去做,有时只需要提供满足C所需要的东西就行。

代理模式分为静态代理(手动实现这些行为的替换) + 动态代理(实现InvocationHandler接口交给虚拟机实现行为的替换)

静态代理

我是一个客户想买一辆车开开,我可以提供买车所有的证件以及买车的行为(具备这些我当然自己就可以去买车了,但是我闲的蛋疼啊,自己去做这些事,毕竟日理万机的工作)
首先呢,我提取了我和中介的共同行为:那就是都可以买车,只是他没有我的相关证件
package com.zndroid.dm.ProxyModel.StaticProxy;/** * Created by luzhenyu on 2017/7/27. */public interface IBuyCar {    void buyCar();}
package com.zndroid.dm.ProxyModel.StaticProxy;/** * Created by luzhenyu on 2017/7/27. */public class Client implements IBuyCar {    private int money;    private String certificate;    private String car;    public String getCar() {        return car;    }    public void setCar(String car) {        this.car = car;    }    public int getMoney() {        return money;    }    public void setMoney(int money) {        this.money = money;    }    public String getCertificate() {        return certificate;    }    public void setCertificate(String certificate) {        this.certificate = certificate;    }    @Override    public void buyCar() {        System.out.println("客户 - 签合同");    }}
去4儿子店,找到一个中介,他客气滴招待了我,建立了我和他的联系(通过这个联系他能够拿到我的相关信息),他本身也具备买车的行为
package com.zndroid.dm.ProxyModel.StaticProxy;/** * Created by luzhenyu on 2017/7/27. * 相当于中介 * 通常建议使用的是聚合式代理而非继承式代理 * 聚合实现方式中代理类聚合了被代理类,且代理类及被代理类都实现了同一个接口,可实现灵活多变。继承式的实现方式则不够灵活; * 比如,在管理员操作的同时需要进行权限的处理,操作内容的日志记录,操作后数据的变化三个功能。三个功能的排列组合有6种, * 也就是说使用继承要编写6个继承了Admin的代理类,而使用聚合,仅需要针对权限的处理、日志记录和数据变化三个功能编写代理类, * 在业务逻辑中根据具体需求改变代码顺序即可。 */public class Proxy implements IBuyCar {    private Client client;//包含客户的引用,这样中介就能给我要相关的证件资料了    public Proxy(Client client) {        this.client = client;    }    @Override    public void buyCar() {        checkMoney$Certificate();        client.buyCar();//具体实体(客户)动作(也就是最终需要客户签合同操作,代理只起到中介作用,而且客户关心的只是买车,证件检查等操作客户无需关心,交给中介做)        shangPai();        client.setCar(jiaoFu());    }    private void checkMoney$Certificate() {        System.out.println("代理 - 资料核实:" + client.getCertificate() + " and " + client.getMoney());//代理做的东西    }    private void shangPai() {        System.out.println("代理 - 上牌");//代理做的东西    }    private String jiaoFu() {        System.out.println("代理 - 交付车辆");//代理做的东西        return "new car";    }}
具体使用:
Client mClient = new Client();mClient.setMoney(100);mClient.setCertificate("ID card");Proxy proxy = new Proxy(mClient);proxy.buyCar();log("客户获得了:" + mClient.getCar());log("----------------我是分割线-----------------");

动态代理

基本和静态代理一样,只是要实现InvocationHandler接口,并告诉虚拟机怎么去处理手动插入的过程
package com.zndroid.dm.ProxyModel.DynamicProxy;/** * Created by luzhenyu on 2017/7/27. */public interface IBuyCar {    void buyCar();}
package com.zndroid.dm.ProxyModel.DynamicProxy;/** * Created by luzhenyu on 2017/7/27. */public class Client implements IBuyCar {    private int money;    private String certificate;    public int getMoney() {        return money;    }    public void setMoney(int money) {        this.money = money;    }    public String getCertificate() {        return certificate;    }    public void setCertificate(String certificate) {        this.certificate = certificate;    }    @Override    public void buyCar() {        System.out.println("客户 - 签合同");    }}
package com.zndroid.dm.ProxyModel.DynamicProxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import static java.lang.System.out;/** * Created by luzhenyu on 2017/7/27. * 一般来说,对代理模式而言,一个主题类与一个代理类一一对应,这也是静态代理模式的特点。 * 但是,也存在这样的情况,有n各主题类,但是代理类中的“前处理、后处理”都是一样的,仅调用主题不同。 * 也就是说,多个主题类对应一个代理类,共享“前处理,后处理”功能,动态调用所需主题,大大减小了程序规模,这就是动态代理模式的特点. * * 动态代理是不需要手写代理类的,但是需要实现InvocationHandler接口,在运行时由虚拟机创建代理, * 实际内部原理 参见<a>http://blog.csdn.net/goskalrie/article/details/52458773<a/> */public class MyInvocationHandler implements InvocationHandler {    private Object target;    public MyInvocationHandler(Object object) {        this.target = object;    }    /**     *@param proxy 被代理的对象     *@param method 被代理对象的方法     *@param args 方法的参数     *@return Object 方法返回值     */    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        if (method.getName().equals("buyCar")) {            checkMoney$Certificate();        }        method.invoke(target, args);        if (method.getName().equals("buyCar")) {            shangPai();        }        return null;    }    private void checkMoney$Certificate() {        String s = "", s1 = "";        try {            Method m = target.getClass().getMethod("getMoney", null);            s = String.valueOf(m.invoke(target, null));            Method m1 = target.getClass().getMethod("getCertificate", null);            s1 = (String)m1.invoke(target, null);        } catch (NoSuchMethodException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        } catch (IllegalAccessException e) {            e.printStackTrace();        }        System.out.println("代理 - 资料核实:" + s + " " + s1);//代理做的东西    }    private void shangPai() {        System.out.println("代理 - 上牌");//代理做的东西    }    public String jiaoFu() {        System.out.println("代理 - 交付车辆");//代理做的东西        return "new car";    }    public Object getProxy() {        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);    }}
具体使用:
MyInvocationHandler invocationHandler = new MyInvocationHandler(client);((IBuyCar) (invocationHandler.getProxy())).buyCar();log("客户获得了:" + invocationHandler.jiaoFu());log("----------------我是分割线-----------------");



【欢迎上码】

【微信公众号搜索 h2o2s2】