设计模式系列--Proxy

一.类图

 

二.意图

为其他对象提供一种代理以控制对这个对象的访问。

三.适用性

a) 在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy 模式。下面是一 些可以使用Proxy 模式常见情况:
1. 远程代理(Remote Proxy )为一个对象在不同的地址空间提供局部代表。
2. 虚代理(Virtual Proxy )根据需要创建开销很大的对象。在动机一节描述的ImageProxy 就是这样一种代理的例子。
3. 保护代理(Protection Proxy )控制对原始对象的访问。保护代理用于对象应该有不同 的访问权限的时候。
4. 智能指引(Smart Reference )取代了简单的指针,它在访问对象时执行一些附加操作。 

b) 它的典型用途包括:

i. 对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它

ii. 当第一次引用一个持久对象时,将它装入内存。

iii. 在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。

四.实例

考研代理本来是我最讨厌的一类人之一,但是今天不得不拿这个例子出来讲一下。对于要考研的人来说,考研代理无疑为他们提供了方便,只要在他这里报名交钱就行了,其他的事情由他为自己安排。

package explore.proxy;

public interface TrainOrgnization {
public void register();
}

package explore.proxy;

public class LingHangOrgnization implements TrainOrgnization {

@Override
public void register() {
System.out.println("欢迎报名领航,祝您考试成功!!");
}

}

package explore.proxy;

public class HaiTianOrgnization implements TrainOrgnization {

@Override
public void register() {
System.out.println("欢迎报名海天,祝您考试成功!");
}

}

package explore.proxy;

public class StudentProxy {
protected TrainOrgnization orgz;

public StudentProxy(TrainOrgnization orgz) {
this.orgz = orgz;
}
}

package explore.proxy;

import java.util.Random;

public class StuentOfLingHangProxy extends StudentProxy implements
TrainOrgnization {
public StuentOfLingHangProxy(LingHangOrgnization orgz) {
super(orgz);
}

//选取座位号
public void chooseSeatNum() {
System.out.println("您的座位号:" + Math.abs(new Random().nextInt()));
}

//打印收据
public void printCheck() {
System.out.println("您的收据");
}

@Override
public void register() {
printCheck();
chooseSeatNum();
orgz.register();
}

}

package explore.proxy;

import java.util.Random;

public class StuentOfHaiTianProxy extends StudentProxy implements
TrainOrgnization {
public StuentOfHaiTianProxy(HaiTianOrgnization org) {
super(org);
}

// 选取座位号
public void chooseSeatNum() {
System.out.println("您的座位号:" + Math.abs(new Random().nextInt()));
}

// 打印收据
public void printCheck() {
System.out.println("您的收据");
}

@Override
public void register() {
printCheck();
chooseSeatNum();
orgz.register();
}

}

package explore.proxy;

public class Client {
public static void main(String[] args) {
StuentOfLingHangProxy lhProxy = new StuentOfLingHangProxy(new LingHangOrgnization());
StuentOfHaiTianProxy htProxy = new StuentOfHaiTianProxy(new HaiTianOrgnization());
//报名领航
lhProxy.register();
//报名海天
htProxy.register();
}
}

上面展示的是静态代理的形式,每一个类对应一个代理类,这样实现起来可能比较麻烦。所以JDK同时提供了动态代理的实现具体的类是InvocationHandlerProxy

相对于上面的例子两个考研机构不变,但是多了一个代理工厂控制类,动态生成代理类:

package explore.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ProxyFactory implements InvocationHandler {
private TrainOrgnization proxied;

public ProxyFactory(TrainOrgnization proxied) {
this.proxied = proxied;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("代理类: " + proxy.getClass() + ", method: "
+ method);
return method.invoke(proxied, args);
}

}

package explore.dynamicproxy;

import java.lang.reflect.Proxy;
import java.util.Random;

public class Client {
// 选取座位号
public void chooseSeatNum() {
System.out.println("您的座位号:" + Math.abs(new Random().nextInt()));
}

// 打印收据
public void printCheck() {
System.out.println("您的收据");
}

public void register(TrainOrgnization orgz) {
chooseSeatNum();
printCheck();
orgz.register();
}

public static void main(String[] args) {
HaiTianOrgnization real = new HaiTianOrgnization();

TrainOrgnization proxy = (TrainOrgnization) Proxy.newProxyInstance(
TrainOrgnization.class.getClassLoader(),
new Class[] { TrainOrgnization.class }, new ProxyFactory(real));

new Client().register(proxy);
}
}





posted @ 2012-03-19 17:02  focusJ  阅读(2828)  评论(0编辑  收藏  举报