1.代理设计模式
代理是基本的设计模式之一,它是开发者为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与"实际“对象的通信,因此,代理通常充当着中间人的角色。
说的简单明了一些,你想买包零食,但是自己不想去超市,所以你把钱交给你的女朋友,你的女朋友拿着钱,替你去超市,给你买了零食(当然,后续她会买什么就不知道了)。你的女朋友就充当了这个代理的角色。你可以把下面的SimpleProxy想象为女朋友的角色。
interface Interface {
void doSomething();
void somethingElse(String str);
}
class RealObject implements Interface{
//被代理对象
@Override
public void doSomething() {
System.out.println("Do something");
}
@Override
public void somethingElse(String str) {
System.out.println("Something else " + str);
}
}
class SimpleProxy implements Interface{
//代理人
private Interface proxied; //被代理对象
public SimpleProxy(Interface proxied){
this.proxied = proxied;
}
@Override
public void doSomething() {
System.out.println("SimpleProxy do something");
proxied.doSomething();
}
@Override
public void somethingElse(String str) {
System.out.println("SimpleProxy something else " + str);
proxied.somethingElse(str);
}
}
public class SimpleProxyDemo {
public static void consumer(Interface iface){
iface.doSomething();
iface.somethingElse("BOBODA");
}
public static void main(String[] args) {
consumer(new RealObject());
consumer(new SimpleProxy(new RealObject()));
}
}
因为consumer()接收的Interface,所以它无法知道正在获取的到底是RealObject还是SimpleProxy,因为这二者都实现了Interface。但是SimpleProxy已经被插入到了客户端和RealObject之间(你女朋友被你扔到了超市和你家的路上),因此它会执行操作,然后调用RealObject上相同的方法。
在任何时刻,只要你想要将额外的操作,从”实际“对象中分离到不同的地方,特别是当你希望很容易做出修改,并作出额外操作时,代理就很有用。比如,你想统计RealObject中方法所执行的时间,但是你又不想将时间统计代码写入RealObject的方法中,就可以使用代理设计模式,让代理帮你去做,同时也不用更改调用接口。
2.Java中的动态代理。
Java中的动态代理比代理的思想更前进一步,因为它可以动态地创建代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型,并确定相应的对策。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class DynamicProxyHandler implements InvocationHandler{
private Object proxied;
public DynamicProxyHandler(Object proxied){
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("**** proxy: " + proxy.getClass() + ", method: " + method +", args : " + args);
if (args != null){
for (Object arg : args){
System.out.println(" " + arg);
}
}
return method.invoke(proxied,args);
}
}
public class SimpleDynamicProxy {
public static void consumer(Interface iface){
iface.doSomething();
iface.somethingElse("banana");
}
public static void main(String[] args) {
RealObject realObject = new RealObject();
consumer(realObject);
Interface proxy = (Interface) Proxy.newProxyInstance(
Interface.class.getClassLoader(),
new Class[]{Interface.class},
new DynamicProxyHandler(realObject));
consumer(proxy);
}
}
输出
Do something
Something else banana
**** proxy: class com.sun.proxy.$Proxy0, method: public abstract void com.thinkInJava.chapter14.Interface.doSomething(), args : null
Do something
**** proxy: class com.sun.proxy.$Proxy0, method: public abstract void com.thinkInJava.chapter14.Interface.somethingElse(java.lang.String), args : [Ljava.lang.Object;@2503dbd3
banana
Something else banana
通过调用静态方法Proxy.newProxyInstance()可以创建动态代理,这个方法需要三个参数,
第一个是类加载器(通常可以从已经被加载的对象中获取其类加载器,然后传递给它)” 谁要被代理呀?"
,第二个是希望该代理实现的接口列表(不是类或抽象类) " 我是代理,我要实现什么接口才能代理你呀? 参照上面静态代理中,代理人要实现相同接口“
,第三个是InvocationHandler接口的一个实现 “构造处理代理的实现” 。
动态代理可以将所有调用重定向到调用处理器,因此,通常会向调用处理器的构造函数传递给一个”实际“对象的引用,从而使得调用处理器在执行其中任务时可以将请求转发。