设计模式之代理模式


代理模式是一个使用率非常高的模式,其定义是为其他对象提供一种代理以控制对这个对象的访问。代理模式也叫委托模式,是一项基本设计技巧。许多其他的模式,如状态模式、策略模式、访问者模式本质上都是在更特殊的场合采用了委托模式。

下面以一个游戏练级的例子分别讲解不同的代理类型:


普通代理:它的要求就是客户端只能访问代理角色,而不能访问真是角色。



public interface IGamePlayer {

	public void login();
	
	public void killBoss();
	
	public void upgrade();
	
}
public class GamePlayer implements IGamePlayer {
	
	private String name;

	@Override
	public void login() {
		System.out.println("用户"+this.name+"登录了");
	}

	@Override
	public void killBoss() {
		System.out.println("用户"+this.name+"击杀了怪");
	}

	@Override
	public void upgrade() {
		System.out.println("用户"+this.name+"升级了");
	}
	
	public GamePlayer(IGamePlayer _gamePlayer, String _name) throws Exception{
		if(_gamePlayer == null){
			throw new Exception("不能创建真实角色");
		}
		this.name = _name;
	}

}
public class GamePlayerProxy implements IGamePlayer {

	private IGamePlayer gamePlayer;
	
	@Override
	public void login() {
		this.gamePlayer.login();
	}

	@Override
	public void killBoss() {
		this.gamePlayer.killBoss();
	}

	@Override
	public void upgrade() {
		this.gamePlayer.upgrade();
	}

	public GamePlayerProxy(String _name) throws Exception{
		gamePlayer = new GamePlayer(this, _name);
	}
}
public class Client {

	public static void main(String[] args) throws Exception {
		IGamePlayer proxy = new GamePlayerProxy("测试人员");
		proxy.login();
		proxy.killBoss();
		proxy.upgrade();
	}
}

在该模式下,调用者只知道代理而不用知道真实的角色是谁,屏蔽了真实角色对高层模块的影响,真实的主题角色想怎么修改就怎么修改,对高层次的模块没有任何影响,只要你实现了接口所对应的方法,该模式非常适合对扩展性要求较高的场合。


此外,代理类除了实现主体接口之外,如果需要在目标对象方法的基础上作前置或后置处理,则可以再实现一个接口,如上面的例子,如果升一级了就加收5元钱,



代理类可以为真实角色预处理消息、过滤消息、消息转发、事后处理消息等功能,并且一个代理类,还可以代理多个真实角色,并且真实角色之间可以有耦合关系。



动态代理:是在实现阶段不用关心代理谁,而在运行阶段才制定代理哪一个对象。像现在流行的面相切面编程,也就是AOP,其核心就是采用动态代理机制。相对来说,自己写代理类的方式就是静态代理。



如图,动态代理实现代理的职责,业务逻辑Subject实现相关的逻辑功能,两者之间没有必然的相互耦合的关系。通知Advice从另一个切面切入,最终在高层模块也就是Client进行耦合,完成逻辑的封装任务。

public interface Subject {

	public void doSomething(String str);
}
public class RealSubject implements Subject {

	@Override
	public void doSomething(String str) {
		System.out.println("真实主题doSomething="+str);
	}

}
public class MyInvocationHandle implements InvocationHandler {
	
	//被代理的对象
	private Object target = null;
	
	public MyInvocationHandle(Object _obj) {
		this.target = _obj;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		//执行被代理的方法
		return method.invoke(this.target, args);
	}

}
public class DynamicProxy<T> {

	public static <T> T newProxyInstance(ClassLoader classLoader, Class<?>[] interfaces, InvocationHandler invocationHandler){
		//寻找JoinPoint连接点,AOP框架使用元数据定义
		if(true){
			//执行前置通知
			(new BeforeAdvice()).exec();
		}
		return (T) Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);
	}
}
public interface IAdvice {
	
	public void exec();
}
public class BeforeAdvice implements IAdvice {

	@Override
	public void exec() {
		System.out.println("执行前置通知");
	}

}


这里可能有读者要问,这样与静态代理有什么区别呢?都是需要实现一个代理类。其实是有区别的,注意看父类,动态代理的主要意图就是解决我们常说的“审计”问题,也就是横向切面编程,在不改变我们已有代码结构的情况下增强或控制对象的行为。

要实现动态代理的首要条件是:被代理类必须实现一个接口。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值