自解代理模式
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。
http://www.cnblogs.com/shijiaqi1066/p/4762995.html
代理模式:为对象提供一种代理,以控制对这个对象的访问。
代理模式的作用:
- 职责清晰。真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
- 代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了中介的作用和保护了目标对象的作用。
- 高扩展性。
以上的废话都来自百度百科。如果不真正敲代码,是不能真正理解到代理模式的好处的。
实现代理模式比较简单,可代理模式却真正能对代码做出很多有效的扩展,并且可以高效的复用代码。
首先有一个行为接口。该接口用于定义需要代理的动作。
public interface Shopping { void shopping(); }
试想普通人去超市买东西。一般买东西有个过程,即“去商场”“购物”“回家”。
一般来说,例如有三类人,美女,男生,大妈。他们都要买东西,但买的东西都不同。
class BeautifulGirl implements Shopping { @Override public void shopping() { System.out.println("买鞋子"); } } class SchoolBoy implements Shopping { @Override public void shopping() { System.out.println("买玩具"); } } class SquareDanceAunt implements Shopping { @Override public void shopping() { System.out.println("买衣服"); } }
这些买东西的人要买东西,他们都需要先“去商场”最后“回家”。那么就需要扩展以上代码。
传统思路
那么一般“扩展”方法如下:
class BeautifulGirl implements Shopping { @Override public void shopping() { System.out.println("去商场"); System.out.println("买鞋子"); System.out.println("回家"); } } class SchoolBoy implements Shopping { @Override public void shopping() { System.out.println("去商场"); System.out.println("买玩具"); System.out.println("回家"); } } class SquareDanceAunt implements Shopping { @Override public void shopping() { System.out.println("去商场"); System.out.println("买衣服"); System.out.println("回家"); } }
现在,我们命令这些人去买东西,执行如下:
public class World { public static void main(String[] args) { Shopping beautifulGirl = new BeautifulGirl(); Shopping schoolBoy = new SchoolBoy(); Shopping squareDanceAunt = new SquareDanceAunt(); beautifulGirl.shopping(); schoolBoy.shopping(); squareDanceAunt.shopping(); } }
这种修改方法违反了开闭原则与DRY原则。
可以直观的感受到,其中以下代码需要重复写,很累。
System.out.println("去商场"); // ...... System.out.println("回家");
静态代理
我们需要给这些人提供一个代理,让代理去简化买东西的过程,把“去商场”,“回家”这个过程却都有代理去做了。
现实中,这种代理一般我们喜欢叫他雷锋。
public class LeiFengProxy implements Shopping { /** * 雷锋侠要服务的对象。 */ private Shopping shoper; /** * 召唤雷锋侠。 * @param shoper */ public LeiFengProxy(Shopping shoper){ this.shoper = shoper; } @Override public void shopping() { System.out.println("去商场"); shoper.shopping(); System.out.println("回家"); } }
有了雷锋这种代理,让这些人去买东西就轻松很多了。
public class World { public static void main(String[] args) { Shopping beautifulGirl = new BeautifulGirl(); Shopping schoolBoy = new SchoolBoy(); Shopping squareDanceAunt = new SquareDanceAunt(); Shopping beautifulGirlProxy = new LeiFengProxy(beautifulGirl); Shopping schoolBoyProxy = new LeiFengProxy(schoolBoy); Shopping squareDanceAuntProxy = new LeiFengProxy(squareDanceAunt); beautifulGirlProxy.shopping(); schoolBoyProxy.shopping(); squareDanceAuntProxy.shopping(); } }
让每个人的代理雷锋去买东西,实际上代理雷锋操作了买东西的这个人,
这种修改精简了代码,不再需要重复写“去商场”“回家”,而且符合开闭原则与DRY。
动态代理
一般动态代理直接使用JDK的动态代理。将与Shopping这个动作的无关的动作直接封装起来。
public class GoShopHandler implements InvocationHandler { /** * 服务对象 */ private Object object; public GoShopHandler(Object object){ this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("去商场"); method.invoke(object,args); System.out.println("回家"); return null; } }
不再需要写代理类。直接生成代理对象。
public class World { public static void main(String[] args) { Shopping beautifulGirl = new BeautifulGirl(); Shopping schoolBoy = new SchoolBoy(); Shopping squareDanceAunt = new SquareDanceAunt(); Shopping beautifulGirlProxy = (Shopping) Proxy.newProxyInstance(beautifulGirl.getClass().getClassLoader(), beautifulGirl.getClass().getInterfaces(), new GoShopHandler(beautifulGirl)); Shopping schoolBoyProxy = (Shopping) Proxy.newProxyInstance(schoolBoy.getClass().getClassLoader(), schoolBoy.getClass().getInterfaces(), new GoShopHandler(schoolBoy)); Shopping squareDanceAuntProxy = (Shopping) Proxy.newProxyInstance(squareDanceAunt.getClass().getClassLoader(), squareDanceAunt.getClass().getInterfaces(), new GoShopHandler(squareDanceAunt)); beautifulGirlProxy.shopping(); schoolBoyProxy.shopping(); squareDanceAuntProxy.shopping(); } }
使用动态代理中扩展代码与原始对象的接口无关。即动态代理比静态代理的优势在于GoShopHandler可以扩展任意“到商场去”的动作,不一定要局限于Shopping。也有可能有些人去商场是去工作的,比如营业员。
public interface Working { void working(); }
public class SalesClerk implements Working { @Override public void working() { System.out.println("上班"); } }
结合GoShopHandler扩展营业员的Working动作。
public class World { public static void main(String[] args) { Shopping beautifulGirl = new BeautifulGirl(); Shopping schoolBoy = new SchoolBoy(); Shopping squareDanceAunt = new SquareDanceAunt(); SalesClerk salesClerk = new SalesClerk(); Shopping beautifulGirlProxy = (Shopping) Proxy.newProxyInstance(beautifulGirl.getClass().getClassLoader(), beautifulGirl.getClass().getInterfaces(), new GoShopHandler(beautifulGirl)); Shopping schoolBoyProxy = (Shopping) Proxy.newProxyInstance(schoolBoy.getClass().getClassLoader(), schoolBoy.getClass().getInterfaces(), new GoShopHandler(schoolBoy)); Shopping squareDanceAuntProxy = (Shopping) Proxy.newProxyInstance(squareDanceAunt.getClass().getClassLoader(), squareDanceAunt.getClass().getInterfaces(), new GoShopHandler(squareDanceAunt)); Working salesClerkProxy = (Working) Proxy.newProxyInstance(salesClerk.getClass().getClassLoader(), salesClerk.getClass().getInterfaces(), new GoShopHandler(salesClerk)); beautifulGirlProxy.shopping(); schoolBoyProxy.shopping(); squareDanceAuntProxy.shopping(); salesClerkProxy.working(); } }
总结一下,代理模式的思想是创建一个代理对象,使用这个对象去操作原始对象(被代理的对象)。从而起到扩展原始对象的动作的目的。并且可以把与原始对象无关的扩展代码抽象到一起去。
代理模式的是AOP的基础,其效果有点像与Windows编程中的Hook技术,只不过这里是面向对象的。
为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处。LaplaceDemon/ShiJiaqi。
http://www.cnblogs.com/shijiaqi1066/p/4762995.html