类图
定义
为其它对象提供一种代理以控制对这个对象的访问
优点
- 职责清晰 真实的角色就是实现的业务逻辑,不用关心其他非本指责的事务
- 高扩展性 具体主题角色不管怎么变化,只要它实现了接口,代理类完全可以在不做任何修改的情况下使用
- 智能化 动态代理是最好的体现,即在运行阶段才指定实际代理对象(Struts如何把表单元素映射到对象上?)
使用场景
典型应用如Spring AOP,Android AIDL
扩展
- 普通代理 要求客户端只能访问代理角色,而不能访问真实角色
- 强制代理 要求客户端必须通过真实角色找到代理角色(演员和经纪人)
- 虚拟代理 指在需要的时候,才初始化主题对象,可以避免被代理对象太多而引起的初始化缓慢问题
静态代理
抽象主题类
public interface Subject {
void request();
}
实体主题类
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject->request()");
}
}
代理类
public class Proxy implements Subject {
// 要代理哪个实现类
private Subject subject = null;
/**
* 通过构造函数传递被代理者
*
* @param subject 被代理者
*/
public Proxy(Subject subject) {
this.subject = subject;
}
/**
* 实现接口中定义的方法
*/
@Override
public void request() {
this.before();// 预处理
this.subject.request();
this.after();// 善后处理
}
/**
* 预处理
*/
private void before() {
System.out.println("预处理");
}
/**
* 善后处理
*/
private void after() {
System.out.println("善后处理");
}
}
静态代理 场景类
public class Client {
public static void main(String[] args) {
//新建主题类
RealSubject realSubject = new RealSubject();
//代理主题类
Subject proxySubject = new Proxy(realSubject);
//执行代理类方法
proxySubject.request();
}
}
运行结果
预处理
RealSubject->request()
善后处理
动态代理
玩家接口
public interface IGamePlayer {
void login(String user, String password);
void killBoss();
void upgrade();
}
实体玩家类
public class GamePlayer implements IGamePlayer {
private String name = "";
/**
* 玩家 实现类
*
* @param _name 玩家名
*/
public GamePlayer(String _name) {
name = _name;
}
@Override
public void killBoss() {
System.out.println(name + "在打怪");
}
@Override
public void login(String user, String password) {
System.out.println("登录名为" + user + "的用户 " + name + "登录成功");
}
@Override
public void upgrade() {
System.out.println(name + "又升了一级");
}
}
动态代理类 借助java自带的代理方法
public class DynamicProxy implements InvocationHandler {
/**
* 被代理者的实例
*/
private Object obj = null;
/**
* 我要代理谁
*
* @param _obj 被代理者
*/
public DynamicProxy(Object _obj) {
this.obj = _obj;
}
/**
* 执行代理
*
* @return 代理类
*/
public Object proxy() {
if (obj != null) {
Class<?> cls = obj.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(), this);
}
throw new RuntimeException("被代理者为空");
}
/**
* 调用被代理的方法
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = method.invoke(this.obj, args);
if (method.getName().equalsIgnoreCase("login")) {
System.out.println("有人登录");
} else if (method.getName().equalsIgnoreCase("upgrade")) {
System.out.println("有人升级了");
}
return result;
}
}
场景类
public class Client {
public static void main(String[] args) {
// 新建玩家类
IGamePlayer player = new GamePlayer("BobbyGu");
// 动态代理一个玩家类
IGamePlayer proxyPlayer = (IGamePlayer) new DynamicProxy(player).proxy();
if (proxyPlayer != null) {
//调用代理类方法
proxyPlayer.login("BobbyGu", "123123");
proxyPlayer.killBoss();
proxyPlayer.upgrade();
}
}
}
运行结果
登录名为BobbyGu的用户 BobbyGu登录成功
有人登录
BobbyGu在打怪
BobbyGu又升了一级
有人升级了