類圖
定義
爲其它對象提供一種代理以控制對這個對象的訪問
優點
- 職責清晰 真實的角色就是實現的業務邏輯,不用關心其他非本指責的事務
- 高擴展性 具體主題角色不管怎麼變化,只要它實現了接口,代理類完全可以在不做任何修改的情況下使用
- 智能化 動態代理是最好的體現,即在運行階段才指定實際代理對象(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又升了一級
有人升級了