浅谈代理模式(Proxy Pattern)

代理模式

代理模式是在实际开发中经常使用的一种设计模式,其定义如下:

为其他对象提供一种代理以控制对这个对象的访问

这句话很好理解,比如在网络中,经常会用到代理,一个请求过来了,那么首先会被代理服务器去响应,代理服务器获得请求后去真正的服务器请求资源,并回应客户发送的请求。用户只需要告诉代理我需要什么东西,至于怎么去找这些东西,用户不用管,由代理服务器去做。

模式组成

代理模式的通用类图如下:
在这里插入图片描述

角色关系作用
Subject抽象主题角色抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,没有特殊的需求
RealSubject具体主题角色也叫被委托角色、被代理角色。是业务逻辑的具体执行者
Proxy代理主题角色也叫委托类、代理类。负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作

为什么使用代理

  • 中介隔离作用:某些情况下,客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
  • 符合开闭原则:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。

表述代码
抽象主题接口:

public interface Subject {

	//随意定义一个方法
	public void request();
}

具体主题角色:

public class RealSubject implements Subject {

	@Override
	public void request() {
		// TODO Auto-generated method stub
		System.out.println("业务处理。。。");
	}

}

代理类:

public class Proxy implements Subject {

	private Subject subject = null;
	
	public Proxy() {
		this.subject = new Proxy();
	}
	public Proxy(Subject _subject) {
		this.subject = _subject;
	}
	@Override
	public void request() {
		// TODO Auto-generated method stub
		this.before();
		this.subject.request();
		this.after();
		
	}
	
	//预处理
	private void before() {
		System.out.println("预处理。。");
	}
	
	//善后处理
	private void after() {
		System.out.println("善后处理。。。");
	}

}

代理模式的分类

为了更好的说明,简单的举个例子:我们都喜欢玩游戏,享受在游戏中肆意妄为的快感(不要误会^ ^),但是日常的升级和各种麻烦的任务确实是挺恶心的,那我们可以雇人帮我们完成日常的升级和任务,不需要我们自己来升级和完成任务。

普通代理

普通代理模式是最简单的一种,要使用代理首先要知道代理,才能访问使用。
那我们先来定义一个抽象游戏类:

public interface IGamePlayer {
	
	//登陆游戏
	public void login(String user, String password);
	
	//杀怪,网络游戏的主要特色
	public void killBoss();
	
	//升级
	public void upgrade();
}

我们定义了几个简单的接口,表示如何登陆游戏,在游戏中杀怪和升级。
定义一个具体的游戏类:

public class GamePlayer implements IGamePlayer {

	private String name = "";
	public GamePlayer(IGamePlayer _gamePlayer, String name) throws Exception {
		if(_gamePlayer == null) {
			throw new Exception("不能创建真实角色!");
		}
		else {
			this.name = name;
		}
	}
	@Override
	public void login(String user, String password) {
		// TODO Auto-generated method stub
		System.out.println("登陆名为:" + user + "的用户" + this.name + "登陆成功");
		
	}

	@Override
	public void killBoss() {
		// TODO Auto-generated method stub
		System.out.println(this.name + "在打怪");
		
	}

	@Override
	public void upgrade() {
		// TODO Auto-generated method stub
		System.out.println(this.name + "又升了一级");
	}

}

这就是在游戏中我们要完成的事情,当然,这个过程是十分简化的。那么定义一个代理,让这个代理来完成替我们打怪升级的过程:

public class GamePlayerProxy implements IGamePlayer {

	private IGamePlayer gamePlayer = null;
	public GamePlayerProxy(String name) {
		// TODO Auto-generated constructor stub
		try {
			gamePlayer = new GamePlayer(this, name);
		} catch(Exception e) {
			//异常
		}
	}
	@Override
	public void login(String user, String password) {
		// TODO Auto-generated method stub
		this.gamePlayer.login(user, password);
	}

	@Override
	public void killBoss() {
		// TODO Auto-generated method stub
		this.gamePlayer.killBoss();
	}

	@Override
	public void upgrade() {
		// TODO Auto-generated method stub
		this.gamePlayer.upgrade();
	}

}

测试类:

public class Client {

	public static void main(String[] args) {
		IGamePlayer proxy = new GamePlayerProxy("张三");
		System.out.println("开始时间:。。。");
		proxy.login("zhangsan", "password");
		proxy.killBoss();
		proxy.upgrade();
		System.out.println("结束时间为:。。。");
	}
}

普通代理的总结:

  • 优点:可以符合在开闭原则的情况下完成对目标对象的功能扩展,进行代理功能。
  • 缺点:需要为每一个服务创建代理类,不易管理。
强制代理

调用者直接调用真实角色,不需要知道代理的存在,其代理的产生是由真实角色决定的。听着是不是挺奇葩的,你必须通过真实角色找到代理角色,否则你没办法使用,也就是说真实角色管理代理角色。这么说,高层模块生成了一个真实的对象,返回的却是代理角色,就好比你和某个明星是朋友,有一件事请想请他帮忙协商,然后你给他打电话:
“在吗,我想见一下xxx明星”
“不行啊,我这几天比较忙,你找我的经济人吧!”
本来想绕过经纪人直接找明星,但是返回的还是经济人。这就是强制代理,你可以不用知道代理的存在,但是你的所作所为还是需要代理为你提供。
在这里插入图片描述
抽象游戏类:

public interface IGamePlayer {
	//登陆游戏
	public void login(String user, String password);
	
	//杀怪,网络游戏的主要特色
	public void killBoss();
	
	//升级
	public void upgrade();
	
	//寻找自己的代理
	public IGamePlayer getProxy();
}

增加了一个getProxy方法,用来返回代理。
具体游戏类:

public class GamePlayer implements IGamePlayer {

	private String name = "";
	private IGamePlayer proxy = null;
	
	public GamePlayer(String name) {
		this.name = name;
	}
	@Override
	public void login(String user, String password) {
		// TODO Auto-generated method stub
		if(this.isProxy()) {
			System.out.println("登陆名为:" + user + "的用户" + this.name + "登陆成功");
		}
		else {
			System.out.println("请使用指定的代理服务器");
		}
	}

	@Override
	public void killBoss() {
		// TODO Auto-generated method stub
		if(this.isProxy()) {
			System.out.println(this.name + "在打怪");
		}
		else {
			System.out.println("请使用指定的代理服务器");
		}
	}

	@Override
	public void upgrade() {
		// TODO Auto-generated method stub
		if(this.isProxy()) {
			System.out.println(this.name + "又升了一级");
		}
	}

	@Override
	public IGamePlayer getProxy() {
		// TODO Auto-generated method stub
		this.proxy = new GamePlayerProxy(this);
		return this.proxy;
	}
	
	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;
	}
	@Override
	public void login(String user, String password) {
		// TODO Auto-generated method stub
		this.gamePlayer.login(user, password);
		
	}

	@Override
	public void killBoss() {
		// TODO Auto-generated method stub
		this.gamePlayer.killBoss();
	}

	@Override
	public void upgrade() {
		// TODO Auto-generated method stub
		this.gamePlayer.upgrade();
	}

	@Override
	public IGamePlayer getProxy() {
		// TODO Auto-generated method stub
		return this;
	}

}

强制代理的概念就是强调要从真实角色查找到代理角色,不允许直接访问真实角色,高层模块只需要调用getProxy就可以访问真实角色的所有方法,根本就不需要产生一个代理出来,代理的管理已经由真实角色生成。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值