设计模式_代理模式



代理 

在client和目标对象之间起到中介的作用,而且能够通过代理对象去掉客户不能看到的内容和服务或者加入客户须要的额外服务

比如

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();
 }
}

上面的样例很easy,权当入门看看。有点感觉。

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


强制代理

//强制代理   必须通过真实类找到代理
//普通代理   通过代理找到真实类
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();
	}

我是菜鸟,我在路上。

原文地址:https://www.cnblogs.com/yjbjingcha/p/6943628.html