代理 proxy 设计模式( 二 )


代理 proxy 设计模式

文章插图
【代理 proxy 设计模式】2.虚拟代理
虚拟代理前面有介绍,就是基于代理模式又做了延迟加载来节省内存,但是如果某个对象要在多个没有固定时序地方使用的时候就要进行判空,也会一定程度上牺牲性能(有点像代理模式+懒汉模式).这里还是拿租房的例子来展示.
这里就假设House是一个很庞大的对象,在创建的时候很耗费资源,那我们就更改成当需要用它的时候才去初始化.这里就在构造的时候先判House的引用是否为空,然后才会初始化House,当然如果这里有多线程并发的话可以根据不同的场景进行加锁或者双检锁来保证线程安全.
[java] view plain copy
(){ if(null==house) house=("",5000); }
[java] view plain copy
=(); Log.i(TAG,"use"); .(); Log.i(TAG,""); .(); .(); Log.i(TAG,"");
3.强制代理
强制代理是反其道而行之的代理模式,一般情况下代理模式都是通过代理来找到真实的对象,而强制代理则是通过真实对象才能找到代理也就是说由真实对象指定代理,当然最终访问还是通过代理模式访问的.从名字还能看出它跟其他代理的一个不同,就是强制用代理.拿上面普通代理的例子来说,看不到实体的House的时候它只能通过代理来访问,但是由于没有限制,也可以直接绕过来访问House,但是强制代理就多了一个限制,必须通过才能访问House.就像一些房东嫌麻烦,有房客直接电话过来说要看房,房东给出一个中介的电话说你跟中介联系吧.
首先需要在接口里面添加一个获取代理的接口
[java] view plain copy
e{ (); (); (); (); }
真实对象实现接口,并在中实例化代理,同时在其他方法里面做代理判断,只有使用自身自定的代理才会正常进行.
[java] view plain copy
{ G=House.class.(); ; ; ;(,){ this.name=name; this.price=price; }@ fo(){ if(()) Log.i(TAG,"-name:"+name+"¥:"+price); else Log.i(TAG,"y"); }@ ct(){ if(()) Log.i(TAG,":"+name+""+ ("HH:mm:ss").(.())); else Log.i(TAG,"y");}@ (){ if(()) Log.i(TAG,"Bill:name-"+name+"$-"+price); else Log.i(TAG,"y"); }@ (){ if(null==proxy) proxy=(this); ; }y(){ if(null==proxy) ; else ; } }
如果这个时候直接操作House对象,或者通过构建的代理来访问都会返回以下结果
代理 proxy 设计模式

文章插图
所以我们必须使用由真实对象指定的代理才可以正常得访问.
[java] view plain copy
=("",5000); house=house.(); Log.i(TAG,"use"); house.(); Log.i(TAG,""); house.(); house.();
但是这里的强制代理有个Bug,强制代理其实并没有生效,还是可以直接访问House,例如我通过下面的方式来进行访问,只是通过创建并获取代理,但是我不用代理还是直接用House的实例进行访问,这个时候还是可以正常访问的.后续会想办法解了这个Bug并且更新上来的.
[java] view plain copy
=("",5000); house.();//这里只是通过创建出代理 Log.i(TAG,"use"); house.(); Log.i(TAG,""); house.(); house.();
4.动态代理
上面介绍的都是自己先写好的代理类,这样代理关系都是固定的,当代理多个真实对象的时候就要写多个代理类,并且会产生冗余的代码,扩展性和可维护性都不高,而动态代理是基于反射实现了在程序运行的过程中才决定代理什么对象.像AOP的核心思想就是动态代理.(这里使用的是Java的动态代理)
既然是动态代理就不需要也不需要实现接口了,这里写一个实现的接口,并且提供一个根据Proxy构建出来的代理实例给.在通过反射调用真实对象具体的方法之前打印出该方法的名字.
[java] view plain copy
{ G=.class.(); ;(){ this.=; .(.().(), .().(),this); }@ (,,[]args){ ; Log.i(TAG,":"+.()); ret=.(,args); ; } }