设计模式_代理模式



代理 

在客户端和目标对象之间起到中介的作用 ,并且可以 通过代理对象去掉客户不能看到的内容和服务或者添加客户需要的额外服务

例如

structs2里面的拦截器,网络代理,翻墙等等。

这里就不多叙述其他高级的代理模式了,学的很肤浅,没有实际应用到项目中去,这个暑假,只是拓宽一下眼界而已,让自己有个印象。

普通代理(静态代理)

public abstract class IGamePlayer {
 public abstract void fightBoss();
 public abstract void login(String uname,String pwd);
 public abstract void upgrade();
}

public class GamePlayer extends IGamePlayer {
 private String name="";
 
 public GamePlayer(String name){
  this.name=name;
 }
 @Override
 public void fightBoss() {
  System.out.println(this.name+"在打怪");
 }
 @Override
 public void upgrade() {
  System.out.println(this.name+"升级了");
 }
 @Override
 public void login(String uname, String pwd) {
  System.out.println(uname+"登录,时间"+new Date());
 }
}

public class GamePlayerProxy extends IGamePlayer {
 private IGamePlayer gamePlayer=null;
 
 public GamePlayerProxy(GamePlayer gamePlayer){
  this.gamePlayer=gamePlayer;
 }
 
 @Override
 public void fightBoss() {
  this.gamePlayer.fightBoss();
 }
 @Override
 public void login(String uname, String pwd) {
  this.before();
  this.gamePlayer.login(uname, pwd);
 }
 @Override
 public void upgrade() {
  this.gamePlayer.upgrade();
  this.after();
 }
 public void before(){
  System.out.println("开始代理");
 }
 
 public void after(){
  System.out.println("结束代理");
 }
}

public class Client {
 
 public static void main(String[] args) {
  GamePlayer player=new GamePlayer("大宝");
  GamePlayerProxy proxy=new GamePlayerProxy(player);
  proxy.login("大宝","a");
  proxy.fightBoss();
  proxy.upgrade();
 }
}

上面的例子非常简单,权当入门看看,有点感觉。

下面来一个有意思的代理,叫做强制代理,意思就是只能通过真实类来找到代理,而上面的静态代理是通过代理来找到真实类,从而达到访问目的。


强制代理

//强制代理   必须通过真实类找到代理
//普通代理   通过代理找到真实类
public abstract class IGamePlayer {
	public abstract void fightBoss();
	public abstract void login(String uname,String pwd);
	public abstract void upgrade();
	public abstract IGamePlayer getProxy();
}

public class GamePlayerProxy extends IGamePlayer {
	private IGamePlayer gamePlayer=null;
	
	public GamePlayerProxy(IGamePlayer gamePlayer){
		this.gamePlayer=gamePlayer;
	}
	
	@Override
	public void fightBoss() {
		this.gamePlayer.fightBoss();
	}

	@Override
	public void login(String uname, String pwd) {
		this.before();
		this.gamePlayer.login(uname, pwd);
	}

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

	public void before(){
		System.out.println("开始代理");
	}
	
	public void after(){
		System.out.println("结束代理");
	}
	
    //暂时没有,就是自己
	@Override
	public IGamePlayer getProxy() {
		return this;
	}
}

public class GamePlayer extends IGamePlayer {
	
	private String name="";
	private IGamePlayer proxy=null;
	
	@Override
	public IGamePlayer getProxy() {
		this.proxy=new GamePlayerProxy(this);
		return this.proxy;
	}
	
	public GamePlayer(String name){
		this.name=name;
	}
	@Override
	public void fightBoss() {
		if(this.isProxy()){
			System.out.println(this.name+"在打怪");
		}else{
			System.out.println("请使用指定的代理访问");
		}
	}

	@Override
	public void upgrade() {
		if(this.isProxy()){
			System.out.println(this.name+"升级了");
		}else{
			System.out.println("请使用指定的代理访问");
		}
	}

	@Override
	public void login(String uname, String pwd) {
		if(this.isProxy()){
			System.out.println(uname+"登录,时间"+new Date());
		}else{
			System.out.println("请使用指定的代理访问");
		}
	}
	private boolean isProxy(){
		if(this.proxy==null){
			return false;
		}else{
			return true;
		}
	}
}

public class Client {
 
	public static void main(String[] args) {
	/*	GamePlayer player=new GamePlayer("大宝");
		player.login("大宝","a");
		player.fightBoss();
		player.upgrade();*/
		
		/*IGamePlayer player=new GamePlayer("大宝");
		IGamePlayer proxy=new GamePlayerProxy(player);
		proxy.login("大宝","a");
		proxy.fightBoss();
		proxy.upgrade();*/
		
		IGamePlayer player=new GamePlayer("大宝");
		IGamePlayer proxy=player.getProxy();
		proxy.login("大宝", "a");
		proxy.fightBoss();
		proxy.upgrade();
	}
}

分析测试          

    第一个直接使用真实类访问,自然无法访问。因为在其业务方法中指定需要代理。

    第二种通过真实类得到一个代理对象,这样的话是通过代理来访问真实类,和静态代理一样。

    第三种通过真实类得到一个代理对象,再实现访问。


动态代理

大致分为四步,其中详细的就不多说了。可以参照博客。 http://www.cnblogs.com/flyoung2008/archive/2013/08/11/3251148.html

1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(...);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{...});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。
生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))


public class GamePlayIH implements InvocationHandler {

//	Class cls=null;  //被代理者
	Object obj=null;  //被代理的实例
	
	public GamePlayIH(Object _obj){
		this.obj=_obj;
	}
	
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		 Object result=method.invoke(this.obj, args);
		 if(method.getName().equalsIgnoreCase("login")){
			 System.out.println("有人用我的账号登陆");
		 }
		 return result;
	}
}


public static void main(String[] args) {
		GamePlayer player = new GamePlayer("大宝");
		
		InvocationHandler handler = new GamePlayIH(player);
		ClassLoader cl = player.getClass().getClassLoader();

		IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl,
				new Class[] { IGamePlayer.class }, handler);
		proxy.login("大宝", "a");
		proxy.fightBoss();
		proxy.upgrade();
	}

这里有个地方需要说明,Proxy仅仅支持interface代理,也就是说,IGamePlayer只能是接口,而不能是抽象类,细心的可能发现上面写的都是使用了抽象类。再细心的可以发现我在实例化GamePlayer("大宝")时没有使用多态,失误失误。  这样看来,动态代理完全是面向接口编程,抽象层面的底层编程。

public interface IGamePlayer {
	
	public void fightBoss();

	public void login(String uname, String pwd);

	public void upgrade();
}

public class GamePlayer implements IGamePlayer {
	private String name="";
	
	public GamePlayer(String name){
		this.name=name;
	}
	public void fightBoss() {
		System.out.println(this.name+"在打怪");
	}
	 

	public void login(String uname, String pwd) {
		System.out.println(uname+"登录,时间"+new Date());
	}
	public void upgrade() {
		System.out.println(this.name+"升级");
	}
}


将上述的多个流程整合成一起

public class DynamicProxy<T> {
	
	public static <T> T newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h){
		//寻找JoinPoint连接点,AOP框架使用元数据定义
		if(true){
			//XXX执行
			System.out.println("执行到这里来了");
		}
		return (T) Proxy.newProxyInstance(loader, interfaces, h);
	}
}

再进一步的整理

public class SubjectDynamicProxy extends DynamicProxy {
	
	public static <T> T  newProxyInstance(IGamePlayer gamePlayer){
		ClassLoader loader=gamePlayer.getClass().getClassLoader();
		Class<?>[] interfaces=gamePlayer.getClass().getInterfaces();
		InvocationHandler handler=new GamePlayIH(gamePlayer);
		return newProxyInstance(loader, interfaces, handler);
 	}
}


调用

public static void main(String[] args) {
		GamePlayer player = new GamePlayer("大宝");
		
		InvocationHandler handler = new GamePlayIH(player);

		IGamePlayer proxy =DynamicProxy.newProxyInstance(player.getClass().getClassLoader(), 
				player.getClass().getInterfaces(), handler);
		proxy.login("大宝", "a");
		proxy.fightBoss();
		proxy.upgrade();
	}


	public static void main(String[] args) {
		GamePlayer player = new GamePlayer("大宝");

		IGamePlayer proxy =SubjectDynamicProxy.newProxyInstance(player);
		
		proxy.login("大宝", "a");
		proxy.fightBoss();
		proxy.upgrade();
	}

我是菜鸟,我在路上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值