代理模式是一种使用效率非常高的模式,其定义:为其他对象提供一种代理以控制对这个对象的访问。
三个角色:
- Subject :一个普通业务类型的定义,无特殊要求
- RealSubject:具体主题角色,也叫做被委托角色、被代理角色,是业务逻辑的执行者
- Proxy代理主题角色:负责对真实角色的应用,把所有抽象主题类定义成的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作。
1. 通用格式:
public interface Subject {
public void request();
}
public class RealSubject implements Subject {
@Override
public void request() {
//doSomething()
}
}
public class Proxy implements Subject {
Subject subject = null;
public Proxy(Subject subject ){
this.subject = subject;
}
@Override
public void request() {
this.doBefore();
this.subject.request();
this.doAfter();
}
private void doBefore(){
}
private void doAfter(){
}
}
代理模式扩展:
2. 普通代理
普通代理是我们知道代理类的存在,然后才能访问,它要求是客户端智能访问代理角色,而不能访问真实角色(类似,我们不能直接google,但是可以通过代理软件访问,这就相当于通过代理访问google,而不是去直接访问)
例如:
简单描述:这是一个模拟游戏的例子,IGamPlayer接口定义了登录,打怪和升级,作为游戏玩家不想自己刷级,于是找代理进行刷级
public interface IGamePlayer {
public void login(String userName,String pwd);
public void killBoss();
public void upgrade();
}
public class GamePlayer implements IGamePlayer {
private String name;
//构造函数限制谁能创建对象,并同时传递用户名
public GamePlayer(IGamePlayer gamePlayer,String name){
if(gamePlayer==null){
System.out.println("不能自己创建用户 !");
}else{
this.name=name;
}
}
@Override
public void login(String userName, String pwd) {
System.out.println("用户"+userName+"登录成功!");
}
@Override
public void killBoss() {
System.out.println(name+" 打怪升级中..");
}
@Override
public void upgrade() {
System.out.println(name+" 升级成功");
}
}
public class GamePlayerProxy implements IGamePlayer{
private IGamePlayer player = null;
public GamePlayerProxy(String name) {
try{
player = new GamePlayer(this,name);//生成真实的角色对象
}catch(Exception ex){
}
}
@Override
public void login(String userName, String pwd) {
this.player.login(userName, pwd);;
}
@Override
public void killBoss() {
this.player.killBoss();
}
@Override
public void upgrade() {
this.player.upgrade();
}
}
测试:
public class Client {
static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
public static void main(String[] args) throws InterruptedException {
IGamePlayer proxy = new GamePlayerProxy("JY");
System.out.println("游戏开始时间为:"+df.format(new Date()));
proxy.login("abc", "123");
proxy.killBoss();
Thread.sleep(2000);
proxy.upgrade();
System.out.println("游戏结束"+df.format(new Date()));
}
}
游戏开始时间为:2016-08-09 17:12:28
用户JY登录成功!
JY 打怪升级中..
JY 升级成功
游戏结束2016-08-09 17:12:30
在该模式下,调用者只知道代理而不知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响,真实的主体角色想怎么修改就怎么修改,对高层次的模块没有任何影响。
3. 强制代理
一般的思维都是通过代理找到真实的角色,但是强制代理却是要”强制”,你必须通过真实角色查找到代理角色,否则不能访问,只有通过真实角色指定的代理类才能访问。就像,去打官司,不能随便指定一个代理律师,只能指定自己的辩护律师才行。
类图修改
代码如下:
public interface IGamePlayer {
public void login(String userName,String pwd);
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;
}
@Override
public IGamePlayer getProxy() {
this.proxy=new GamePlayerProxy(this);//指定代理是谁
return this.proxy;
}
@Override
public void login(String userName, String pwd) {
if(isProxy()){
System.out.println("用户"+userName+"登录成功!");
}else{
System.out.println("你家代理呢?");
}
}
@Override
public void killBoss() {
if(isProxy()){
System.out.println(name+" 打怪升级中..");
}else{
System.out.println("你家代理呢?");
}
}
@Override
public void upgrade() {
if(isProxy()){
System.out.println(name+" 升级成功");
}else{
System.out.println("你家代理呢?");
}
}
//检验是否代理访问
public boolean isProxy(){
if(this.proxy==null)
return false;
else{
return true;
}
}
}
强制代理类:
public class GamePlayerProxy implements IGamePlayer,IProxy{
private IGamePlayer player = null;
public GamePlayerProxy(IGamePlayer player) {
this.player = player;
}
@Override
public void login(String userName, String pwd) {
this.player.login(userName, pwd);;
}
@Override
public void killBoss() {
this.player.killBoss();
}
@Override
public void upgrade() {
this.player.upgrade();
this.count();
}
@Override
public IGamePlayer getProxy() {
return this;
}
@Override
public void count() {
System.out.println("升级耗费100¥");
}
}
访问测试:
public class Client {
static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
public static void main(String[] args) throws InterruptedException {
IGamePlayer player = new GamePlayer("JY");
IGamePlayer proxy = player.getProxy();
System.out.println("游戏开始时间为:"+df.format(new Date()));
proxy.login("abc", "123");
proxy.killBoss();
Thread.sleep(2000);
proxy.upgrade();
System.out.println("游戏结束"+df.format(new Date()));
}
}
只有真实用户指定了代理对象即player.getProxy()才可以访问。其他的均不行。
强制代理的概念就是从真实角色查找到代理角色,不允许直接访问真实 角色,高层模块只要调用getProxy就可以访问真实角色的所有方法,不需要产生一个代理来,代理的管理已经由真实角色自己完成。
游戏开始时间为:2016-08-09 17:23:28
用户JY登录成功!
JY 打怪升级中..
JY 升级成功
升级耗费100¥
游戏结束2016-08-09 17:23:30
代码参照:设计模式之禅
动态代理好难,下节在继续研究。