您的位置:首页 > 其它

动态代理与静态代理之略见

2014-08-13 14:44 141 查看
最近一直在学习和讨论设计模式,同时也是在讨论如何学习,才能让加速度达到最大.对于如何学习,你肯定会说,我从小学就开始学习了,到大学毕业都学习了几十年了,难倒我还不会学习吗.其实想想,你真的会学习吗.读完大学,接受的一直都是应试教育,填鸭式的学习.老师给什么学什么,学不会还怪老师教的不好.
那么如何学习呢,学习要从生活中来,在回归到生活中.整个学习的过程中,为什么要贯穿整个学习的过程,为什么有学习这个,学习这个的好处是什么,学习这个内容能解决什么问题.
在这次讨论设计模式,我对代理模式情有独钟.其中代理模式分为静态代理和动态代理.

1.静态代理

1.1概念

所谓的静态代理就是指程序员创建好代理类,编译时直接生产代理类的字节码文件.

1.2类图



1.3 birdTimeProxy类代码

public class BirdTimeProxy implements  Flyeable{
	
	 public BirdTimeProxy(Flyeable f) {
	        super();
	        this.f = f;
	    }
	 Flyeable f;
	
	@Override
	public void fly() {
		f.fly();
		
	}
	
}

1.4客户端代码

public static void main(String[] args) throws Exception  {
	Bird f=new Bird();
	BirdTimeProxy fyb=new BirdTimeProxy(f);
	
	Flyeable fly=fyb;
	fly.fly();
}

2.动态代理

2.1概念

所谓的动态代理就是在程序运行时,通过反射机制动态生产代理类.动态代理可以提供对另一个对象的访问,同时隐藏实际对象的具体事实。代理一般会实现它所表示的实际对象的接口。代理可以访问实际对象,但是延迟实现实际对象的部分功能,实际对象实现系统的实际功能,代理对象对客户隐藏了实际对象。客户不知道它是与代理打交道还是与实际对象打交道。

2.2为什么使用

可以对请求进行任何处理

2.3 类图



2.4dynamicproxy代理类:

/**
 * 实现在方法调用前后控制台输出
 * @author wanwan
 *
 */
public class dynamicProxy implements InvocationHandler {
	//要代理的原始对象
	private Object obj;
	
	public dynamicProxy(Object obj){
		super();
		this.obj=obj;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		Object result=null;
		//调用之前
		doBefore();
		//调用原始对象的方法
		result=method.invoke(obj, args);
		//调用之后
		doAfter();
		return result;
	}
	private void doAfter() {
		System.out.print("after method invoke");
		
	}
	private void doBefore() {
		System.out.print("before method invoke");
		
	}

}


2.4 客户端代码

public static void main(String[] args) {
		Flyeable fly=new Bird();
		InvocationHandler  handler=new dynamicProxy(fly);
		
		//创建动态代理对象
		Flyeable proxy=(Flyeable) Proxy.newProxyInstance(
				fly.getClass().getClassLoader(), fly.getClass().getInterfaces(), handler);
		proxy.fly();
		
	}


3.多个对象需要代理时....

代理一个对象的时候,而代理的对象不变的话,使用静态代理或者使用动态代理,都没有多大的区别,那么如果需要代理的对象经常性的发生变化或者需要代理多个对象的时候.静态代理会出现什么情况呢.先用静态代理处理看看:
第一步:写一个接口和接口的实现.最后一步不管是在动态代理还是在静态代理中,这个类就是必须存在的.在这里,我们增加一个Moveanble接口和Tank实现类.
第二步:写一个代理TankTimeProxy.代码如下:
public class TankTimeProxy implements Moveable {
    public TankTimeProxy(Moveable t) {
        super();
        this.t = t;
    }
    Moveable t;
@Override
public void move(){
        t.move();
	}
}


第三步:修改客户端代码,具体修改代码如下:
Tank t=new Tank();
TankTimeProxy ttp=new TankTimeProxy(t);
Moveable moveable=ttp;
moveable.move();
代理两个对象的UML图如下所示:



从图中我们可以看出,每增加一个真实对象,都会相对应的增加一个代理类.

若使用动态代理,就不用这么麻烦了.代理类不用进行修改,只需要在添加接口和接口实现类后,直接修改客户端代码就可以了.客户端修改后的代码如下:
Moveable mv=new Tank();
InvocationHandler  handler1=new dynamicProxy(mv);
		
//创建动态代理对象
Moveable proxy1=(Moveable) Proxy.newProxyInstance(
				mv.getClass().getClassLoader(), mv.getClass().getInterfaces(), handler1);
proxy1.move();


对应的UML图如下:



4.总结

从整体的代码来看,似乎静态代理要简单很多,一旦代理对象发生了改变或增加,就要从新添加代理类.若对象变化比较大的话,添加的代理类会增多,会造成代理类泛滥,难以管理.如果使用动态代理,只需要以一个代理就可以解决了,动态代理中的代理类把静态代理中的真实对象和代理类之间的耦合给解开了.降低了耦合度.所以,在真实对象容易发生改变或者是真是对象比较多的时候,往往会考虑使用动态代理了.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: