参考:设计模式之禅
1. 例子
public interface IGamePlayer {
void login(String username,String password);
void killBoss();
void upgrade();
}
public class GamePlayer implements IGamePlayer {
private String username;
public GamePlayer(String username) {
this.username = username;
}
@Override
public void login(String username, String password) {
System.out.println(username + " login");
}
@Override
public void killBoss() {
System.out.println(username + " kill boss");
}
@Override
public void upgrade() {
System.out.println(username + " upgrade");
}
}
public class GamePlayerProxy implements IGamePlayer {
private IGamePlayer gamePlayer;
public GamePlayerProxy(IGamePlayer gamePlayer) {
this.gamePlayer = gamePlayer;
}
@Override
public void login(String username, String password) {
this.gamePlayer.login(username, password);
}
@Override
public void killBoss() {
this.gamePlayer.killBoss();
}
@Override
public void upgrade() {
this.gamePlayer.upgrade();
}
}
public class Client {
public static void main(String[] args) {
GamePlayer zhangsan = new GamePlayer("zhangsan");
GamePlayerProxy gamePlayerProxy = new GamePlayerProxy(zhangsan);
gamePlayerProxy.login("zhangsan","password");
gamePlayerProxy.killBoss();
gamePlayerProxy.upgrade();
}
}
2. 定义
Proxy Pattern provide a surrogate or placeholder for another object to control access to it, 为其他对象提供一个代理以控制对这个对象的访问。
- Subject抽象主题角色,可以是接口或抽象类;
- RealSubject,被代理角色,业务逻辑的具体执行者;
- Proxy,代理类
3. 应用
3.1 优点
- 职责清晰,被代理类负责具体业务逻辑,不管其他;
- 高扩展性,被代理类可以随时被替换,只要实现接口即可,代理类不用修改;
- 智能化。
3.2 具体应用
Spring的AOP。
4. 扩展
4.1 普通代理
客户端只能返回代理角色,不能访问真实角色。改造两种的构造函数即可。
4.2 强制代理
只能通过真实觉得找到代理角色,好比我找某个明星谈代言的事,明星说我很忙,请找我的经纪人谈。
4.3 代理有个性
可以在目标对象方法基础上作增强,例如在升级的时候收钱。
4.4 动态代理
AOP,面向切面编程,其实现的基础就是动态代理。动态代理指在实现阶段不关心代理谁,而是在运行的时候指定代理哪个对象。
InvocationHandler是JDK提供的动态代理接口。
public interface IGamePlayer {
void login(String username,String password);
void killBoss();
void upgrade();
}
public class GamePlayer implements IGamePlayer {
private String username;
public GamePlayer(String username) {
this.username = username;
}
@Override
public void login(String username, String password) {
System.out.println(username + " login");
}
@Override
public void killBoss() {
System.out.println(username + " kill boss");
}
@Override
public void upgrade() {
System.out.println(username + " upgrade");
}
}
public class GamePlayerIH implements InvocationHandler {
private Object object;
public GamePlayerIH(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(this.object, args);
}
}
public class Client {
public static void main(String[] args) {
GamePlayer zhangsan = new GamePlayer("zhangsan");
GamePlayerIH gamePlayerIH = new GamePlayerIH(zhangsan);
ClassLoader classLoader = zhangsan.getClass().getClassLoader();
IGamePlayer proxyInstance = (IGamePlayer) Proxy.newProxyInstance(classLoader, new Class[]{IGamePlayer.class}, gamePlayerIH);
proxyInstance.login("zhangsan","password");
proxyInstance.killBoss();
proxyInstance.upgrade();
}
}