设计模式-代理模式 Java示例
Posted Ruffian-痞子
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-代理模式 Java示例相关的知识,希望对你有一定的参考价值。
代理模式定义:为其他对象提供一种代理,以控制对这个对象的访问。在某些情况下,对一个对象的访问或者引用存在困难时,通过代理对象起到连接客户端和目标对象的桥梁作用
这个定义还是挺清晰的,先不纠结什么是访问困难的情况,先了解如何通过一个代理对象连接 客户端(需要调用目标对象的地方)和 目标对象。等到实际开发中遇到访问存在困难的时候,自然就能想到使用代理模式解决,所以设计模式真的不是强行使用的,而是在某些特定情况下自然而就使用了
OK,现在模拟一个场景:代购
代购的场景大家都很常见了,比如小明想要买一部苹果笔记本MAC,只能到香港买,小明没有通行证,所以找代购。
1.静态代理
创建一个接口:购买需求
public interface IPurchase
/**
* 购买MAC
*/
void buyMac();
创建一个接口实现类,购买mac. 此处代表小明,他想要购买mac
public class PurchaseImpl implements IPurchase
@Override
public void buyMac()
System.out.println("购买Mac");
由于小明无法直接购买,所以找了一个代理。创建一个代理购买类
public class PurchaseProxy implements IPurchase
//委托人(小明)
private PurchaseImpl mPurchaseImpl;
public PurchaseProxy(PurchaseImpl purchaseImpl)
mPurchaseImpl = purchaseImpl;
@Override
public void buyMac()
System.out.println("代理去香港...");
//帮小明买mac
mPurchaseImpl.buyMac();
代理类需要实现购买需求 implements IPurchase
,帮谁购买?帮小明购买 public PurchaseProxy(PurchaseImpl purchaseImpl)
实现与小明挂钩,代理实现购买,但是他需要先到香港去,或者做一些其他操作,然后才是真正帮小明购买mac mPurchaseImpl.buyMac();
执行
public static void main(String args[])
IPurchase purchase = new PurchaseProxy(new PurchaseImpl());
purchase.buyMac();
输出结果
代理去香港…
购买Mac
嗯,代码很清晰,小明有购买需求,需要实现购买接口。代理帮小明购买,同样需要实现购买接口,同时代理可以做一些购买之外的事情,比如说去香港,或者收取代购费用,这些操作都是可以在代理类中实现
以上我们通过静态代理的模式,实现了代购帮小明购买mac的场景。但是我们发现,好像这个代购只能为小明服务,因为在构造函数中绑定了 PurchaseImpl
同时在 baymac()
也是使用这个对象的 baymac()
如果代购想多赚点钱,帮所有人购买mac呢?怎么实现?
2.动态代理
前面说了,代购不满足现状,想帮所有有需要的人购买mac,于是他改变了策略,他说我可以帮你们代购,无论是谁只要有需求,告诉我就行了。我就会帮你们买回来。这时候就需要用动态代理了
public class PurchaseProxy implements InvocationHandler
//委托人(任何人都可以)
private Object mTargetObj;
//创建代理(接受委托)
public Object newProxyInstance(Object object)
this.mTargetObj = object;
return Proxy.newProxyInstance(mTargetObj.getClass().getClassLoader(), mTargetObj.getClass().getInterfaces(), this);
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
System.out.print("代理去香港...帮>>>");
Object temp = method.invoke(mTargetObj, args);
return temp;
此时,小东,小刚…等等其他有需求的客人也想要购买mac
public class PurchaseImplXiaoD implements IPurchase
@Override
public void buyMac()
System.out.println("小东购买Mac");
public class PurchaseImplXiaoG implements IPurchase
@Override
public void buyMac()
System.out.println("小刚购买Mac");
执行代购
public static void main(String args[])
PurchaseProxy purchaseProxy = new PurchaseProxy();
//帮小东代购
IPurchase purchase = (IPurchase) purchaseProxy.newProxyInstance(new PurchaseImplXiaoD());
purchase.buyMac();
//帮小刚代购
purchase = (IPurchase) purchaseProxy.newProxyInstance(new PurchaseImplXiaoG());
purchase.buyMac();
输出结果:
代理去香港,帮>>>小东购买Mac
代理去香港,帮>>>小刚购买Mac
动态代理通过 Java 的反射机制,实现了动态绑定委托人(委托对象)
3.动态代理分析
Proxy.newProxyInstance()
方法
/**
*根据传入的目标返回一个代理对象
*
**/
//CLassLoader loader:类的加载器
//Class<?> interfaces:得到全部的接口
//InvocationHandler h:得到InvocationHandler接口的子类的实例
Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
方法参数解释
//该方法用于为代理指定类装载器、一组接口及调用处理器生成动态代理类实例
//第一个参数指定产生代理对象的类加载器,需要将其指定为和目标对象同一个类加载器
//第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象的实现接口
//第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法
//返回值:根据传入的目标返回一个代理对象
使用
//创建代理(接受委托)
public Object newProxyInstance(Object object)
this.mTargetObj = object;
return Proxy.newProxyInstance(mTargetObj.getClass().getClassLoader(), mTargetObj.getClass().getInterfaces(), this);
object
委托人(被代理对象)通过参数传入,
1.通过 mTargetObj.getClass().getClassLoader()
获取委托人的类加载器,传给代理对象 (代理对象和委托人需要同一个类加载器)
2.通过 mTargetObj.getClass().getInterfaces()
获取委托人实现的所有接口,传给代理对象 (代理对象和委托人需要实现一样的接口)
3.this
表示当前 InvocationHandler
对象(被拦截的方法需要执行当前 InvocationHandler 的 invoke 方法 )
然后返回一个代理对象。
InvocationHandler
接口
public interface InvocationHandler
//Object proxy : 被代理的对象(委托人)
//Method method: 表示原对象被调用的方法
//Object[] args: 方法调用时所需要参数
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
我们修改一下 buyMac()
方法添加参数,用于演示获取方法被调用时得到参数
public interface IPurchase
/**
* 购买MAC
* @param model 型号
* @param number 数量
*/
void buyMac(String model, int number);
public class PurchaseImpl implements IPurchase
@Override
public void buyMac(String model, int number)
System.out.println("购买Mac. 型号:" + model + " 数量:" + number);
public class PurchaseProxy implements InvocationHandler
//委托人(任何人都可以)
private Object mTargetObj;
//创建代理(接受委托)
public Object newProxyInstance(Object object)
this.mTargetObj = object;
return Proxy.newProxyInstance(mTargetObj.getClass().getClassLoader(), mTargetObj.getClass().getInterfaces(), this);
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
System.out.println("start>>> args==null?" + (args == null));
if (args != null)
for (int i = 0; i < args.length; i++)
System.out.println("args:" + args[i]);
//调用目标方法
Object temp = method.invoke(mTargetObj, args);
System.out.println("end>>>");
return temp;
public static void main(String args[])
PurchaseProxy purchaseProxy = new PurchaseProxy();
IPurchase purchase = (IPurchase) purchaseProxy.newProxyInstance(new PurchaseImpl());
//型号:pro 数量:5
purchase.buyMac("pro", 5);
args
参数数组表示 void buyMac(String model, int number);
方法的参数列表[String,int],如果 void buyMac();
是没有参数的方法,那么 args
为 null . 看一下运行结果
代理执行开始>>> args == null ?false
args:pro
args:5
购买Mac. 型号:pro 数量:5
代理执行结束>>>
以上便是对静态代理模式,动态代理模式的一点分析。讲完…
以上是关于设计模式-代理模式 Java示例的主要内容,如果未能解决你的问题,请参考以下文章