根据Design Pattern描述,常用Proxy设计模式分为四种:virtual proxy, remote proxy,protection proxy和smart reference,相应的句子如下:
1. A remote proxy provides a local representative for an object in a different address space
2. A virtual proxy creates expensive objects on demand.
3. A protection proxy controls access to the original object. Protection proxies are useful when objects should have different access rights.
4.A smart reference is a replacement for a bare pointer that performs a additional actions when an object is accessed. Typical uses include
① counting the number of reference to the real object so that it can be freed automatically when there are no more references(also called smart pointer)
② loading a persistent object into memory when it's first referenced
③ checking that the real object is locked before it's accessed to ensure that no other object can change it.
remote proxy 保存为一个远端对象的引用,当Client需要相应的方法时,会把访问的参数传递给本地的一个proxy对象,然后本地的proxy对象将参数进行编码转发给远端的实际对象。virtual proxy往往用于延迟初始化,对于一些对象的构建比较复杂和消耗空间和性能时,我们往往会使用延迟初始化这样的技术。通过这种代理模式,能将复杂对象的初始化给封装好,而客户端直接与代理进行交互,当实际要使用相应的方法时,才进行实例化具体对象并转发相应的方法给具体的对象。也就是说,对于客户端来讲,Proxy和Real Object直接并无区别。一般来说,当实际初始化Real Object后,Proxy会保存其一个引用。
下面就写一个protection proxy的静态代理和动态代理的例子。
package net.liuyx.test;
public class ProxyTest {
public static void main(String[] args){
Bureau iface = (Bureau) new Secretary();
iface.sign();
iface.eat();
}
}
//某局
interface Bureau{
void sign();
void eat();
}
//请局长吃饭和签字要经过秘书这一关
class Secretary implements Bureau{
private final Head head;
Secretary(){
head = new Head();
}
public void sign(){
head.sign();
}
public void eat(){
head.eat();
}
private static class Head implements Bureau{
public void sign(){System.out.println("header sign!");}
public void eat(){System.out.println("ask the head to eat successly");};
}
}
其输出为
![](https://img-my.csdn.net/uploads/201205/13/1336924303_1627.jpg)
很显然,局长这个类被秘书给保护起来了,转发给局长的方法都会经过秘书这个代理。下面写一个关于动态代理的实现。动态代理会多一个InvocationHandler类的实现,该类用来为代理转发具体的参数:
package net.liuyx.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
Bureau head = (Bureau) new Head();
Bureau secretary = (Bureau) Proxy.newProxyInstance(Bureau.class
.getClassLoader(), new Class[] { Bureau.class },
new DefaultHandler(head));//动态产生代理,在第二个Demo中,并没有为Secretary写代码,Proxy的这个静态方法会动态产生一个代理,该方法需要穿几个参数:ClassLoad对象,被代理对象实现的接口列表(记住,是接口列表,不包含抽象类),和一个InvocationHandler对象
doSomething(secretary);
}
public static void doSomething(Bureau b){
b.eat();
b.sign();
}
}
// 某局
interface Bureau {
void sign();
void eat();
}
class Head implements Bureau {
@Override
public void sign() {
System.out.println("header sign!");
}
@Override
public void eat() {
System.out.println("ask the head to eat successly");
}
}
class DefaultHandler implements InvocationHandler {
Object proxied;
DefaultHandler(Object proxied) {
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("proxy handler the request to the real object");
System.out.println("It's method is: " + method.getName()
+ " and is params is " + args);
return method.invoke(proxied, args);//InvocationHandler的精髓就在这个方法里了,通过反射调用实际被代理对象的方法,并传进参数
}
}
输出:
其他几种代理模式的编写方法也类似,在此就不赘述了。只不过在Virtual Proxy模式中,在具体操作被代理对象时才实例化对象,比如调用eat 和sign时才实例化该对象,而不是在构造器中实例化。
其实Protection proxy代理模式有点像Decorator模式,但装饰器模式往往是给一个对象动态添加一个或多个职责,两者的出发点不一样。而protected的出发点是为了控制实际对象的访问。