设计模式之代理模式

    xiaoxiao2021-03-25  119

    代理,一言以蔽之,就是第三方、中介的意思,比如卖家和买家之间不能直接交易,就需要一个中间人沟通两边以促成交易,和生活中的代理商、代理服务器之类其实都是同一种东西。

    代理模式分为静态代理和动态代理两种,先介绍比较简单的静态代理。

    静态代理

    静态代理可将买家的方法调用传给代理,在代理方法内部,实际调用卖家对象的相同方法,从而完成实际方法的调用。

    通过两方面要求实现静态代理

    将卖家对象置于代理类中,如作为代理类的一个域代理类提供卖家的接口方法

    动态代理

    静态代理只能代理一个类的方法请求,那么当我们需要代理多个类的方法请求时,可用的办法有:

    在代理类中重新添加多个类对象的域,然后对外提供相应的接口新建多个代理类(这个太臃肿了)

    动态代理用一种更加简洁、优雅的方式解决了上述问题,即根据代理方法请求动态地创建代理,并动态地处理代理方法调用。

    重要方法

    Proxy静态newProxyInstance方法用来创建动态代理 loader表示类加载对象interfaces表示代理对象实现的所有方法接口h代表统一转发方法的调用处理器。

    根据代码结果可知

    loader只是提供一个类加载器,跟返回对象类型无关。interfaces 决定返回对象的类型是Interfaces数组里面的任意一种类型,相当于返回的Object实现了interfaces中所有的方法接口,从方法的角度和多态的定义来看,Object是interface中任意class的对象。InvocationHandler是动态代理执行调用转发的接口,要创建实现该接口的调用处理类,必须实现其抽象方法abstract Object invoke(Object proxy, Method method, Object[] args),利用反射机制使用Method.invoke()将请求转发给被代理对象(卖家)完成方法调用。

    静态与动态代理对比

    静态代理:顾客把请求发给代理,代理的方法实现是在其内部创建实际服务者对象,然后调用实际服务者(卖家)对象的实际方法完成顾客请求。静态代理不仅可以有选择地提供实际服务者的部分接口方法,而且能在方法体内部调用实际服务者方法前后,添加属于自己的一些操作,这点类似于继承中的super调用。 代理流程:

    动态代理:顾客同样是把请求传给动态代理,但是在处理请求上,动态代理只是充当中间人或者中转站的角色,在动态代理中并不进行实际处理,只是将顾客请求(连同方法参数)转发给实际服务者,然后由实际服务者调用相应方法,完成请求。这其实有点通信中继站的意味了。 代理流程:

    动态代理示例

    //买家接口 public interface Customer { int order(String goods, Perchasing perchasing); boolean cancelOrder(int orderId, Perchasing perchasing); } //买家 public class Lucy implements Customer { public int order(String goods, Perchasing perchasing) { return perchasing.acceptOrder(goods); } public boolean cancelOrder(int orderId, Perchasing perchasing) { return perchasing.cancelOrder(orderId); } } //海外代购接口 public interface Perchasing { int acceptOrder(String goods); boolean cancelOrder(int orderId); } //实际代购者 public class WomanInUK implements Perchasing { private ArrayList<String> goodsList = new ArrayList<String>(); public int acceptOrder(String goods) { goodsList.add(goods); int orderId = goodsList.indexOf(goods) + 1; System.out.println("Proxy : " + this.getClass().getName() + "\ngoods : " + goods + ", Order " + orderId); return orderId; } public boolean cancelOrder(int orderId) { // String cancelGoods = goodsList.get(orderId); goodsList.remove(orderId - 1); System.out.println("Proxy : " + this.getClass().getName() + "\nCacnel Order : " + orderId); return true; } } //动态代理类 public class PerchasingDynamicProxy implements InvocationHandler { private Object proxied; public PerchasingDynamicProxy(Object proxied){ this.proxied = proxied; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("proxy : " + proxy.getClass() + "\nmethod :" + method + "\nargs :" + args); if (args != null) { for(Object arg : args) System.out.println("Method Parameter : " + arg); } System.out.println("-------------Invoke Dynamic Proxy-----------"); //调用实际代理WomanInUK的对象方法 return method.invoke(proxied, args); } } //海外代购测试 public class OverseasPerchasing { public static void main(String[] args) { Lucy lucy = new Lucy(); WomanInUK realProxy = new WomanInUK(); //调用真实代理 lucy.order("MacBook Pro", realProxy); System.out.println("---------------Order----------------"); //调用动态代理 Perchasing perchasingProxy = (Perchasing) Proxy.newProxyInstance( Customer.class.getClassLoader(), new Class[] {Perchasing.class, Customer.class}, new PerchasingDynamicProxy(realProxy)); int order = lucy.order("SurfaceBook", perchasingProxy); //取消订单 System.out.println("-----------Cacnel Orders-------------"); if (lucy.cancelOrder(order, perchasingProxy)) { System.out.println("Canceling Orders Succeeds! "); } } } ---------- //输出结果 Proxy : com.hwl.proxy.WomanInUK goods : MacBook Pro, Order 1 ---------------Order---------------- proxy : class com.sun.proxy.$Proxy0 method :public abstract int com.hwl.proxy.Perchasing.acceptOrder(java.lang.String) args :[Ljava.lang.Object;@232204a1 Method Parameter : SurfaceBook -------------Invoke Dynamic Proxy----------- Proxy : com.hwl.proxy.WomanInUK goods : SurfaceBook, Order 2 -----------Cacnel Orders------------- proxy : class com.sun.proxy.$Proxy0 method :public abstract boolean com.hwl.proxy.Perchasing.cancelOrder(int) args :[Ljava.lang.Object;@4aa298b7 Method Parameter : 2 -------------Invoke Dynamic Proxy----------- Proxy : com.hwl.proxy.WomanInUK Cacnel Order : 2 Canceling Orders Succeeds!
    转载请注明原文地址: https://ju.6miu.com/read-25285.html

    最新回复(0)