设计模式(二)代理模式

代理模式是一种使用效率非常高的模式,其定义:为其他对象提供一种代理以控制对这个对象的访问。


 三个角色:

  • 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


       静态代理关系,Proxy类通过编译器编译成class文件,当系统运行时,此class已经存在了。这种静态的代理模式固然在访问无法访问的资源,增强现有的接口业务功能方面有很大的优点,但是大量使用这种静态代理,会使我们系统内的类的规模增大,并且不易维护;并且由于Proxy和RealSubject的功能 本质上是相同的,Proxy只是起到了中介的作用,这种代理在系统中的存在,导致系统结构比较臃肿和松散。



代码参照:设计模式之禅


动态代理好难,下节在继续研究。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值