定义:
为其他对象一种代理以控制对这个对象的访问。
代理模式也叫作委托模式,它是一项基本设计技巧,许多其他模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式,而且在日常的应用中,代理模式提供非常好的访问控制。在一些著名的开元然间中也经常见到他的身影,如Struts2的Form元素映射就采用了代理模式(准确的说是动态代理模式)。
通用代码:
抽象主题类
抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。
public interface Subject {
// 定义一个方法
public void request();
}
真实主题类
也叫作被委托角色,被代理角色,是业务逻辑的具体执行者。
publc class RealSubject implements Subject {
// 实现方法
public void request() {
// 业务逻辑处理
}
}
代理类
也叫作委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作。
public class Proxy implements Subject {
// 要代理哪个实现类
private Subject subject = null;
// 默认被代理类
public Proxy() {
this.subject = new Proxy();
}
// 通过构造函数传递代理者
public Proxy(Object... objects) {}
// 实现接口中定义的方法
public void request() {
this.before();
this.subject.request();
this.after();
}
// 预处理
public void before() {
// do Something
}
// 善后处理
public void after() {
// do Something
}
}
一个代理类可以代理多个被委托者或被代理者,因此一个代理类具体代理哪个真实主题角色,是由场景类决定的。当然,最简单的情况就是一个主题类和一个代理类,这是最简单的代理模式。在通常情况下,一个接口只需要一个代理类就可以了,具体代理哪个实现类由高层模块来决定,也就是在代理的构造函数中传递被代理类,你要代理谁就产生该代理的实例,然后把被代理者传递进来,该模式在实际的项目应用中使用比较广泛。
优点:
- 职责清晰
真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事务,附带的结果就是编码简洁清晰。
- 高扩展性
具体主题角色是随时都会发生变化的,只要它实现了接口,甭管他如何变化,都逃不脱如来佛的手掌(接口),那我们的代理完全就可以在不做任何修改的情况下使用。
- 智能化
例如Struts是如何把表单元素映射到对象上的。
使用场景:
代理模式的使用场景非常多,大家可以看看Spring AOP,这是一个非常典型的动态代理。
扩展:
1、普通代理
普通代理是我们要知道代理的存在,然后才能访问;
2、强制代理
强制代理是调用者直接调用真是角色,而不用关心代理是否存在,其代理的产生是由真是角色决定的。
3、代理是有个性的
4、动态代理
最佳实践:
代理模式应用的非常广泛,大到一个系统框架、企业平台,小到代码片段、事务处理,稍不留意就用到代理模式。可能该模式是大家接触最多的模式,而且有了AOP大家写代理就更加简单了,有类似Spring AOP和AspectJ这样非常优秀的工具,拿来主义即可!不过大家可以看看源代码,特别是调试时,只要看到类似$Proxy()这样的结构,你应该知道这是一个动态代理了。
代码案例:
游戏者接口
public interface IGamePlayer {
// 登录游戏
public void login(String user,String password);
// 杀怪,网络游戏的主要特色
public void killBoss();
// 升级
public void upgrade();
}
游戏者
public GamePlayer implements IGamePlayer {
private String name ="";
// 通过构造函数传递名称
public GamePlayer(String _name) {
this.name = _name;
}
// 打怪,最期望的就是杀boss
public void killBoss() {
System.out.println(this.name +"在打怪!");
}
// 进游戏之前你肯定要登录吧,这是一个必要条件
public void login(String user, String password) {
System.out.println("登录名为" + user + "的用户" + this.name + "登录成功!");
}
// 升级,升级有很多方法,花钱买是一种,做任务也是一种
public void upgrade() {
System.out.println(this.name + " 又升级了!");
}
}
代练者
public class GamePlayerProxy implements IGamePlayer {
private IGamePlayer gamePlayer = null;
// 通过构造函数传递要对谁进行代练
public GamePlayerProxy(IGamePlayer _gamePlayer) {
this.gamePlayer = _gamePlayer;
}
// 代练杀怪
public void killBoss() {
this.gamePlayer.killBoss();
}
// 代练登录
public void login(String user, String password) {
this.gamePlayer.login(user, password);
}
}
场景类
public class Client {
public static void main(String[] args) {
// 定义一个痴迷的玩家
IGamePlayer player = new GamePlayer("张三");
// 然后再定义一个代练者
IGamePlayer proxy = new GamePlayerProxy(player);
// 开始打游戏,记下时间戳
System.out.println("开始时间是:2017-01-01 23:27");
proxy.login("zhangSan","password");
// 开始杀怪
proxy.killBoss();
// 升级
proxy.upgrade();
// 记录结束游戏时间
System.out.println("结束时间是:2017-01-02 01:30");
}
}
普通代理的游戏者
public class GamePlayer implements IGamePlayer {
private String name ="";
// 构造函数限制谁能创建对象
public GamePlayer(IGamePlayer _gamePlayer, String _name) throws Exception {
if(_gamePlayer == null) {
throws new Exception("不能创建真实角色!");
} else {
this.name = _name;
}
}
// 打怪,最期望的就是杀老怪
public void killBoss() {
System.out.println(this.name +"在打怪!");
}
// 进游戏之前你肯定要登录吧,这是一个必要条件
public void login(String user, String password) {
System.out.println("登陆名为" + user + "的用户" + this.name + "登录成功!");
}
// 升级,升级有很多方法,花钱买也是一种,做任务也是一种
public void upgrade() {
System.out.println(this.name + "又升了一级!");
}
}
// 普通代理的代理者
public class GamePlayerProxy implements IGamePlayer {
private IGamePlayer gamePlayer = null;
// 通过构造函数传递要对谁进行代练
public GamePlayerProxy(String name) {
try{
gamePlayer = new GamePlayer(this.name);
} catch (Exception e) {
// TDO 异常处理
}
}
// 打怪,最期望的就是杀老怪
public void killBoss() {
this.gamePlayer.killBoss();
}
// 进游戏之前你肯定要登录吧,这是一个必要条件
public void login(String user, String password) {
this.gamePlayer.login(user, password);
}
// 升级,升级有很多方法,花钱买也是一种,做任务也是一种
public void upgrade() {
this.gamePlayer.upgrade();
}
}
// 普通代理的场景类
public class Client {
public static void main(String[] args) {
// 然后再定义一个代练者
IGamePlayer proxy = new GamePlayerProxy("张三");
// 开始打游戏,记下时间戳
System.out.println("开始时间是:2017-01-01 23:27");
proxy.login("zhangSan","password");
// 开始杀怪
proxy.killBoss();
// 升级
proxy.upgrade();
// 记录结束游戏时间
System.out.println("结束时间是:2017-01-02 01:30");
}
}
// 强制代理的接口类
public interface IGamePlayer {
// 登录游戏
public void login(String user , String password);
// 杀怪,这是网络游戏的 主要特色
public void killBoss();
//升级
public void upgrade();
// 每个人都可以找一下自己的代理
public IGamePlayer getProxy();
}
// 强制代理的真实角色
public class GamePlayer Implements IGamePlayer {
private String name = "";
// 我的代理是谁
private IGamePlayer proxy = null;
public GamePlayer(String _name) {
this.name = _name;
}
// 找到自己的代理
public IGamePlayer getProxy() {
this.proxy = new GamePlayerProxy(this);
return this.proxy;
}
// 打怪,最期望的是杀老怪
public void killBoss() {
if(this.isProxy()) {
System.out.println(this.name + "在打怪!");
} else {
System.out.println("请使用指定的代理访问");
}
}
// 进游戏之前你肯定要登录游戏吧,这是一个必要条件
public void login(String user , String password) {
if(this.isProxy()) {
System.out.println("登陆名为" + user + "的用户" + this.name + "登录成功!");
} else {
System.out.println("请使用指定的代理访问");
}
}
// 升级,升级有很多方法,花钱买是一种,做任务也是一种
public void upgrade(){
if(this.isProxy()) {
System.out.println(this.name + " 又升了一级!");
} else {
System.out.println("请使用指定的代理访问");
}
}
// 校验是否是代理访问
private boolean isProxy() {
if(this.proxy == null) {
return false;
} else {
return true;
}
}
}
// 强制代理的代理者
public class GamePlayerProxy implements IGamePlayer {
private IGamePlayer gamePlayer = null;
// 通过构造函数传递要对谁进行代练
public GamePlayerProxy(IGamePlayer _gamePlayer) {
this.gamePlayer = _gamePlayer;
}
// 打怪,最期望的就是杀老怪
public void killBoss() {
this.gamePlayer.killBoss();
}
// 进游戏之前你肯定要登录吧,这是一个必要条件
public void login(String user, String password) {
this.gamePlayer.login(user, password);
}
// 升级,升级有很多方法,花钱买也是一种,做任务也是一种
public void upgrade() {
this.gamePlayer.upgrade();
}
// 代理的代理暂时还没有,就是自己
public IgamePlayer getProxy() {
return this;
}
}
// 强制代理的场景类
public class Client {
public static void main(String[] args) {
// 定义一个游戏的角色
IGamePlayer player = new GamePlayer("张三");
// 获得指定的代理
IGamePlayer proxy = player.getProxy();
// 开始打游戏,记下时间戳
System.out.println("开始时间是:2017-01-01 23:27");
proxy.login("zhangSan","password");
// 开始杀怪
proxy.killBoss();
// 升级
proxy.upgrade();
// 记录结束游戏时间
System.out.println("结束时间是:2017-01-02 01:30");
}
}
// 代理是有个性的
代理类的接口
public interface IProxy {
// 计算费用
public void count();
}
// 代理类
public class GamePlayerProxy implements IGamePlayer, IProxy {
private IGamePlayer gamePlayer = null;
// 通过构造函数传递要对谁进行代练
public GamePlayerProxy(IGamePlayer _gamePlayer) {
this.gamePlayer = _gamePlayer;
}
// 代练杀怪
public void killBoss() {
this.gamePlayer.killBoss();
}
// 代练登录
public void login(String user, String password) {
this.gamePlayer.login(user, password);
}
// 代练升级
public void upgrade() {
this.gamePlayer.upgrade();
this.count();
}
// 计算费用
public void count() {
System.out.println("升级总费用是:150元");
}
}