代理模式:简单讲实现就是代理者和被代理者都实现了同一个接口,代理者内部一般有被代理的对象得引用来实现代理功能,客户调用的时候是对接口的引用,所以客户不在意他引用的是原本的对象还是代理者,只要实现接口它就能识别并调用方法。
在学设计模式时,保护代理举了Java内置的Proxy的例子,说实话,我看到头昏了 (+﹏+)~。
怎么说呢,好像理解了保护模式,却在例子里找不到匹配的类和接口。
看着类图和代码好久,才发现了关键的地方。
保护模式的类图:
这里说的实现了Subject接口的代理对象Proxy和java本身的Proxy完全是两个不同的对象。
应该是我们调用的Proxy代理对象是由java内置的Proxy生成的。
Proxy本身不是代理类,它的作用是生成满足条件的代理对象。
Proxy本身的静态方法:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
Class<?>[] interfaces,
InvocationHandler h)
返回的才是代理对象。
这里我引用下别人的代码:
//代理和被代理对象都实现的接口
interface SellFisher {
int sellFish();
}
//被代理对象,实现了SellFisher接口
public class ConcreteSellFisher implements SellFisher {
public int sellFish() {
System.out.println("my fish is delicious!!");
return 10;
}
}
//实现了InvocationHandler接口的对象,用在生成代理对象是的参数
public class ProxySellFisher implements InvocationHandler {
private SellFisher sell;
public ProxySellFisher(SellFisher sell) {
this.sell = sell;
}
public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
System.out.println("the fish price higher");
return (Integer)method.invoke(sell, args)+10;
/*这里是筛选的过程,一般是用method.getName()获取到调用到的方法名,和对应的方法比较后判断处理方式再将method.invoke()方法的返回值返回,第二个参数args是代理调用方法时传入的参数,这里还可以对参数进行修改。*/
}
}
public class ClientTest {
public static void main(String args[]) {
SellFisher s = new ConcreteSellFisher();
InvocationHandler p = new ProxySellFisher(s);
Object obj = Proxy.newProxyInstance(s.getClass().getClassLoader(), s.getClass().getInterfaces(), p);
/*这里调用Proxy的静态方法newProxyInstance(),返回了真正用到的代理对象*/
((SellFisher)obj).sellFish();
}
}
在代码中:
Proxy.newProxyInstance(s.getClass().getClassLoader(), s.getClass().getInterfaces(), p);
第一个参数被代理对象的类加载器
第二个参数是被代理对象实现的接口数组
第三个参数是实现了InvocationHandler的对象,它的作用是筛选。
这里补充点知识:Java有个Class对象,Class的实例表示在运行中的Java应用程序的类或者接口,就比如说类A,A.getClass()就得到A的Class对象,通过类加载器ClassLoader就能实例化A对象,这是在单件模式下,既私有构造方法的情况下能得到类对象的方法之一。
至于InvocationHandler接口,我现在也只知道它是配合Proxy创建代理的时候用到,让Proxy生成的代理按照invoke方法去过滤代理方法的调用。
讲到这里难点应该都能知道了,其它的简单看下代码应该都能理解。