代理模式是一种很常见的设计模式,他使用代理对象完成用户请求,屏蔽用户对真实对象的访问。在软件开发中使用代理模式的原因很多,比如因为安全原因,需要屏蔽客户端直接访问真实对象,也可能是为了提升性能,对真实对象进行封装,从而达到延迟加载的目的。
代理模式的通用类图如下:
代理模式主要参与者有四个:
角色 | 作用 |
主题接口 | 定义代理类和真实主题的对外供方方法,也是代理类代理真实主题的方法 |
真实主题 | 真正实现业务逻辑的类 |
代理类 | 用来代理和封装真实主题 |
Main | 客户端,使用代理和真实主题接口完成一些工作 |
例如:假设客户端有根据用户请求,去数据库查询数据的功能,在查询数据前需要获得数据库连接对象,软件开启时,初始化系统所有类,此时尝试获得数据库连接,当数据库有大量类似操作时,所有这些操作的叠加会使的系统的启动速度变得非常慢。为此使用代理模式封装对数据库查询中的初始化操作,当系统启动时初始化这个代理类而非真实的数据库查询类,然而代理什么都没有做,所以它的构造是相当迅速的。
通过类图我们可以知道代理类中存在一个对被代理对象的引用,最终的操作还是由真实对象来做的,只不过在做之前通过代理类做些功能上的增强,例如:我们在开发过程中想要测试一下方法的只想时间,如果没有代理类的情况下我们会怎么做呢?
我们可能会再每个方法的逻辑前后加上时间的输出用于计算耗费时间,可是如果每个方法都这样加的话,那么有一天如果想去掉怎么办,需要打开各个类把时间输出这段代码删掉,那如果有一天领导又想看看耗费时间怎么办。。。。
通用类图的代码如下:
/**
* 抽象主题类
*
*/
public abstract class Subject {
// 抽象主题的方法
protected abstract void request();
}
/**
* 真实的主题角色
*
*/
public class RealSubject extends Subject {
/**
* 具体的实现逻辑
*/
@Override
protected void request() {
System.out.println("收到请求....");
}
}
/**
* 代理类
*
*/
public class Proxy extends Subject {
private Subject subject;
public Proxy(Subject subject) {
this.subject = subject;
}
/**
* 代理类同真是的主题角色实现同一个抽象类或者接口,
* 因为代理类是要代理真实的角色,既然是代理,那么代理就应该具有真是角色拥有的功能
*/
@Override
protected void request() {
System.out.println("开始时间");
subject.request();
System.out.println("结束时间");
}
}
其实在我们的应用的框架中有好多代理模式的应用,想Struts、Spring中都有代理模式的使用,由于代理模式的应用如此频繁,以至于java中也增加了代理模式的代码
代理模式分为静态代理和动态代理两种,下面以小明打游戏为例说一下者两种模式:
静态代理:
public interface GamePlayer {
// 打怪
public void daguai();
// 升级
public void upgrade();
}
public class Xiaoming implements GamePlayer {
/**
* 打怪
*/
@Override
public void daguai() {
System.out.println("小明开始打怪了.....");
}
/**
* 升级
*/
@Override
public void upgrade() {
System.out.println("小明,升级了....");
}
}
public class GamePlayerProxy implements GamePlayer, Billing {
private GamePlayer player;
public GamePlayerProxy(GamePlayer player) {
this.player = player;
}
/**
* 打怪
*/
@Override
public void daguai() {
player.daguai();
}
/**
* 升级
*/
@Override
public void upgrade() {
player.upgrade();
// 计费
this.account();
}
/**
* 计费
*/
@Override
public void account() {
System.out.println("计费成功");
}
}
/**
* 计费接口
*
*/
public interface Billing {
// 计费
public void account();
}
动态代理:
public interface IGamePlayer {
// 登陆
public void login(String user, String pwd);
// 打怪
public void daguai();
// 升级
public void upgrade();
}
public class Xiaoming implements IGamePlayer {
private String name;
public Xiaoming(String name) {
this.name = name;
}
/**
* @param user
* @param pwd
*/
@Override
public void login(String user, String pwd) {
System.out.println("登陆名为:" + user + "的用户:" + this.name + "登陆成功");
}
/**
*
*/
@Override
public void daguai() {
System.out.println(this.name + "在打怪");
}
/**
*
*/
@Override
public void upgrade() {
System.out.println(this.name + "游戏升级了");
}
}
public class GamePlayerHandler implements InvocationHandler {
// 被代理类
private Class cls;
// 被代理者实例
private Object object;
public GamePlayerHandler(Object object) {
this.object = object;
}
/**
* 调用被代理的方法
*
* @param proxy
* @param method
* @param args
* @return
* @throws Throwable
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method,
* java.lang.Object[])
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
Object result = method.invoke(object, args);
return result;
}
}