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

xiaoxiao2021-02-28  117

代理模式说白了就是中介,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】

转载请注明原文地址: https://www.6miu.com/read-39354.html

最新回复(0)