`
zhoushuping
  • 浏览: 45641 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java设计模式之(代理)Proxy

阅读更多
设计模式之Proxy(代理)

转自:

http://www.blogjava.net/lusm/archive/2007/08/08/135355.html

http://www.blogjava.net/lusm/archive/2007/08/09/135433.html

设计模式中定义 : Fronting for another object(为其他对象提供一种代理以控制对这个对象的访问).


为什么要使用Proxy?
1.授权机制不同级别的用户对同一对象拥有不同的访问权利,如Jive论坛系统中,就使用Proxy进行授权机制控制,访问论坛有两种人:注册用户和游客(未注册用户),Jive中就通过类似ForumProxy这样的代理来控制这两种用户对论坛的访问权限.

2.某个客户端不能直接操作到某个对象,但又必须和那个对象有所互动.
举例两个具体情况:
(1)如果那个对象是一个是很大的图片,需要花费很长时间才能显示出来,那么当这个图片包含在文档中时,使用编辑器或浏览器打开这个文档,打开文档必须很迅速,不能等待大图片处理完成,这时需要做个图片Proxy来代替真正的图片.

(2)如果那个对象在Internet的某个远端服务器上,直接操作这个对象因为网络速度原因可能比较慢,那我们可以先用Proxy来代替那个对象.

总之原则是,对于开销很大的对象,只有在使用它时才创建,这个原则可以为我们节省很多宝贵的Java内存. 所以,有些人认为Java耗费资源内存,我以为这和程序编制思路也有一定的关系.

其他需要使用proxy的情况这里不一一列举,大家在实践的时候再慢慢体会。

如何使用Proxy?

proxy主要分为静态代理模式和动态代理模式。

静态代理模式 :

一个简单的例子:

view plaincopy to clipboardprint?

   1. package com.proxy; 
   2. /**
   3.  * 电脑批发商。
   4.  */ 
   5. public interface Computer { 
   6.     public void buy(String name); 
   7. } 

package com.proxy; /** * 电脑批发商。 */ public interface Computer { public void buy(String name); }

view plaincopy to clipboardprint?

   1. package com.proxy; 
   2. /**
   3.  * 联想电脑公司。
   4.  */ 
   5. public class Lenovo implements Computer { 
   6.     @Override 
   7.     public void buy(String name) { 
   8.         System.out.println(name + "联想公司产品"); 
   9.     } 
  10. } 

package com.proxy; /** * 联想电脑公司。 */ public class Lenovo implements Computer { @Override public void buy(String name) { System.out.println(name + "联想公司产品"); } }

view plaincopy to clipboardprint?

   1. package com.proxy; 
   2. /**
   3.  * 三星电脑公司。
   4.  */ 
   5. public class SamSung implements Computer { 
   6.     @Override 
   7.     public void buy(String name) { 
   8.         System.out.println(name + "三星公司产品"); 
   9.     } 
  10. } 

package com.proxy; /** * 三星电脑公司。 */ public class SamSung implements Computer { @Override public void buy(String name) { System.out.println(name + "三星公司产品"); } }

view plaincopy to clipboardprint?

   1. package com.proxy; 
   2. /**
   3.  * 电脑销售代理商。
   4.  */ 
   5. public class ComputerProxy implements Computer { 
   6.      
   7.     private Computer computer; 
   8.      
   9.     public ComputerProxy(Computer computer) { 
  10.         this.computer = computer; 
  11.     } 
  12.      
  13.     @Override 
  14.     public void buy(String name) { 
  15.         System.out.println("before method invoking"); 
  16.         computer.buy(name); 
  17.         System.out.println("after method invoking"); 
  18.     } 
  19. } 

package com.proxy; /** * 电脑销售代理商。 */ public class ComputerProxy implements Computer { private Computer computer; public ComputerProxy(Computer computer) { this.computer = computer; } @Override public void buy(String name) { System.out.println("before method invoking"); computer.buy(name); System.out.println("after method invoking"); } }

view plaincopy to clipboardprint?

   1. package com.proxy; 
   2. /**
   3.  * 买电脑的客户,一个买三星电脑,一个买联想电脑。 
   4.  */ 
   5. public class BuyComputer { 
   6.     public static void main(String[] args) { 
   7.         Computer proxy1 = new ComputerProxy(new SamSung()); 
   8.         proxy1.buy("我想买一台三星电脑"); 
   9.         Computer proxy2 = new ComputerProxy(new Lenovo()); 
  10.         proxy2.buy("我想买一台联想电脑"); 
  11.     } 
  12. } 

package com.proxy; /** * 买电脑的客户,一个买三星电脑,一个买联想电脑。 */ public class BuyComputer { public static void main(String[] args) { Computer proxy1 = new ComputerProxy(new SamSung()); proxy1.buy("我想买一台三星电脑"); Computer proxy2 = new ComputerProxy(new Lenovo()); proxy2.buy("我想买一台联想电脑"); } }

运行结果:

before method invoking
我想买一台三星电脑三星公司产品
after method invoking
before method invoking
我想买一台联想电脑联想公司产品
after method invoking

在上例中,Lenovo.java和SamSung.java是真正实现buy方法的类,ComputerProxy为代理类,Computer为他们共同的基类。

ComputerProxy里面并没有创建新的方法,它根据传入对象的类型(Lenovo或者SamSung)来决定到底是用Lenovo里面的 buy方法,还是SamSung里面的buy方法,它充当的是Lenovo和SamSung的前台,也由此对应了代理模式的定义:Fronting for another object 。

动态代理模式:

         前面一个文章里的代码很简单(只是让大家了解什么是代理),实现的是静态代理,做为电脑代理商的ComputerProxy,在电脑行业 为电脑生产商(三星,联想)和客户提供服务,提供各种方便。
        郁闷的是,如果我现在增加一个行业,比如下面要讲到的Car汽车行业,那么,我们只能增加一个代理了,也就是说我们要再写一个CarProxy代码,我们现在假设我们有很多个行业,那么,无疑我们的工作量开始大了,有没有什么办法让我们的代理商实现跨行业代理 呢?
        答案是:可以。这就是我们这里讲的动态代理产生存在的意义了。

如果你要增加一个汽车行业,则会增加以下代码:

view plaincopy to clipboardprint?

   1. package com.proxy.dynamic; 
   2. /**
   3.  * 汽车批发商。
   4.  */ 
   5. public interface Car { 
   6.     public void buy(String name); 
   7. } 

package com.proxy.dynamic; /** * 汽车批发商。 */ public interface Car { public void buy(String name); }

view plaincopy to clipboardprint?

   1. package com.proxy.dynamic; 
   2. /**
   3.  * 劳斯莱斯批发商。
   4.  */ 
   5. public class RollsRoyce implements Car { 
   6.     public void buy(String name) { 
   7.         System.out.println(name + "劳斯莱斯公司产品"); 
   8.     } 
   9. } 

package com.proxy.dynamic; /** * 劳斯莱斯批发商。 */ public class RollsRoyce implements Car { public void buy(String name) { System.out.println(name + "劳斯莱斯公司产品"); } }

view plaincopy to clipboardprint?

   1. package com.proxy.dynamic; 
   2. /**
   3.  * 汽车销售代理商。
   4.  */ 
   5. public class CarProxy implements Car { 
   6.      
   7.     private Car car; 
   8.      
   9.     public CarProxy(Car car) { 
  10.         this.car = car; 
  11.     } 
  12.      
  13.     @Override 
  14.     public void buy(String name) { 
  15.         System.out.println("before method invoking"); 
  16.         car.buy(name); 
  17.         System.out.println("after method invoking"); 
  18.     } 
  19. } 

package com.proxy.dynamic; /** * 汽车销售代理商。 */ public class CarProxy implements Car { private Car car; public CarProxy(Car car) { this.car = car; } @Override public void buy(String name) { System.out.println("before method invoking"); car.buy(name); System.out.println("after method invoking"); } }

如果有很多行业的话,代理类(上面例子中的CarProxy)也会很多,工作量变大的同时,也带来了可维护性的问题。如果用动态代理的话,可以很方便的解决这个问题。

下面我们在上面静态代理模式例子的基础上,增加一个汽车行业。

完整的代码如下:

view plaincopy to clipboardprint?

   1. package com.proxy; 
   2. /**
   3.  * 电脑批发商。
   4.  */ 
   5. public interface Computer { 
   6.     public void buy(String name); 
   7. } 

package com.proxy; /** * 电脑批发商。 */ public interface Computer { public void buy(String name); }

view plaincopy to clipboardprint?

   1. package com.proxy; 
   2. /**
   3.  * 联想电脑公司。
   4.  */ 
   5. public class Lenovo implements Computer { 
   6.     @Override 
   7.     public void buy(String name) { 
   8.         System.out.println(name + "联想公司产品"); 
   9.     } 
  10. } 

package com.proxy; /** * 联想电脑公司。 */ public class Lenovo implements Computer { @Override public void buy(String name) { System.out.println(name + "联想公司产品"); } }

view plaincopy to clipboardprint?

   1. package com.proxy; 
   2. /**
   3.  * 三星电脑公司。
   4.  */ 
   5. public class SamSung implements Computer { 
   6.     @Override 
   7.     public void buy(String name) { 
   8.         System.out.println(name + "三星公司产品"); 
   9.     } 
  10. } 

package com.proxy; /** * 三星电脑公司。 */ public class SamSung implements Computer { @Override public void buy(String name) { System.out.println(name + "三星公司产品"); } }

view plaincopy to clipboardprint?

   1. package com.proxy.dynamic; 
   2. /**
   3.  * 汽车批发商。
   4.  */ 
   5. public interface Car { 
   6.     public void buy(String name); 
   7. } 

package com.proxy.dynamic; /** * 汽车批发商。 */ public interface Car { public void buy(String name); }

view plaincopy to clipboardprint?

   1. package com.proxy.dynamic; 
   2. /**
   3.  * 劳斯莱斯批发商。
   4.  */ 
   5. public class RollsRoyce implements Car { 
   6.     public void buy(String name) { 
   7.         System.out.println(name + "劳斯莱斯公司产品"); 
   8.     } 
   9. } 

package com.proxy.dynamic; /** * 劳斯莱斯批发商。 */ public class RollsRoyce implements Car { public void buy(String name) { System.out.println(name + "劳斯莱斯公司产品"); } }

动态代理类:

view plaincopy to clipboardprint?

   1. package com.proxy.dynamic; 
   2. import java.lang.reflect.InvocationHandler; 
   3. import java.lang.reflect.Method; 
   4. import java.lang.reflect.Proxy; 
   5. public class AllProxy implements InvocationHandler { 
   6.      
   7.     private Object object; 
   8.      
   9.     public Object bind(Object object) { 
  10.         this.object = object; 
  11.          
  12.         return Proxy.newProxyInstance(object.getClass().getClassLoader(),  
  13.                 object.getClass().getInterfaces(), this); 
  14.     } 
  15.      
  16.     @Override 
  17.     public Object invoke(Object proxy, Method method, Object[] args) 
  18.             throws Throwable { 
  19.         System.out.println("before method invoking"); 
  20.         Object result = method.invoke(object, args); 
  21.         System.out.println("after method invoking"); 
  22.         return result; 
  23.     } 
  24. } 

package com.proxy.dynamic; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class AllProxy implements InvocationHandler { private Object object; public Object bind(Object object) { this.object = object; return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("before method invoking"); Object result = method.invoke(object, args); System.out.println("after method invoking"); return result; } }

view plaincopy to clipboardprint?

   1. package com.proxy.dynamic; 
   2. public class BuyAll { 
   3.     public static void main(String[] args) { 
   4.         AllProxy allProxy = new AllProxy(); 
   5.         Computer proxy1 = (Computer)allProxy.bind(new SamSung()); 
   6.         proxy1.buy("SamSung"); 
   7.          
   8.         Computer proxy2 = (Computer)allProxy.bind(new Lenovo()); 
   9.         proxy2.buy("Lenovo"); 
  10.          
  11.         Car proxy3 = (Car)allProxy.bind(new RollsRoyce()); 
  12.         proxy3.buy("RollsRoyce"); 
  13.     } 
  14. } 

package com.proxy.dynamic; public class BuyAll { public static void main(String[] args) { AllProxy allProxy = new AllProxy(); Computer proxy1 = (Computer)allProxy.bind(new SamSung()); proxy1.buy("SamSung"); Computer proxy2 = (Computer)allProxy.bind(new Lenovo()); proxy2.buy("Lenovo"); Car proxy3 = (Car)allProxy.bind(new RollsRoyce()); proxy3.buy("RollsRoyce"); } }

运行结果:

before method invoking
SamSung三星公司产品
after method invoking
before method invoking
Lenovo联想公司产品
after method invoking
before method invoking
RollsRoyce劳斯莱斯公司产品
after method invoking

动态代理模式中,只需要一个代理类(AllProxy)就完成了所有的代理工作,减少代码。
分享到:
评论

相关推荐

    Java设计模式——代理设计模式(静态代理和动态代理)

    在Java编程中,设计模式是一种解决常见问题的模板或最佳实践,它可以帮助开发者编写更加灵活、可维护和可扩展的代码。代理设计模式是其中的一种,它的主要作用是在不修改原有对象的基础上,为对象添加额外的功能或者...

    Java设计模式之代理模式(结构)

    ### Java设计模式之虚拟代理模式详解 #### 一、引言 在软件工程领域,设计模式作为一种被广泛接受的最佳实践,对于提高代码质量和可维护性起着至关重要的作用。其中,“代理模式”作为结构型设计模式之一,在解决...

    java 设计模式之代理模式(Proxy Pattern)实现代码及设计详解:动态代理模式、静态代理模式

    Java设计模式是软件开发中的重要概念,它提供了一套通用的解决方案模板,使得代码更加可复用、可扩展。在这些模式中,代理模式(Proxy Pattern)是一种常用的结构型设计模式,它允许我们为一个对象创建一个代理,该...

    JAVA设计模式之代理模式实例

    在Java编程领域,设计模式是一种解决常见问题的模板或最佳实践,它被广泛应用于软件开发中以提高代码的可读性、可维护性和可扩展性。代理模式是设计模式的一种,它提供了一种对目标对象进行增强或者控制访问的方式。...

    Java设计模式-代理模式例子

    在这个“Java设计模式-代理模式例子”中,我们可能能看到如何创建静态代理类,以及如何利用`Proxy`和`InvocationHandler`创建动态代理。源码分析可以帮助我们更好地理解代理模式的实现细节,并能将其运用到自己的...

    设计模式之代理模式proxy

    **设计模式之代理模式(Proxy Pattern)** 设计模式是软件工程中的一种最佳实践,它是在特定情境下解决常见问题的模板。代理模式是其中一种行为设计模式,它的核心思想是为一个对象提供一个替身或者代理,以控制对...

    JAVA设计模式(代理模式)

    **Java设计模式——代理模式详解** 代理模式是软件设计模式中的一个重要组成部分,它在Java编程中扮演着举足轻重的角色。代理模式的核心思想是为一个对象提供一个替身,这个替身即代理对象,代理对象可以控制对原...

    JAVA设计模式chm文档

    设计模式之Proxy(代理) 设计模式之Adapter(适配器) 设计模式之Composite(组合) 设计模式之Decorator(油漆工) 设计模式之Bridge 设计模式之Flyweight(享元) 行为模式: 设计模式之Template 设计模式之Memento(备忘机制...

    设计模式之代理模式proxy.zip

    代理模式是一种常用的设计模式,它在软件开发中扮演着重要的角色。代理模式允许我们为一个对象创建一个代理,这个代理对象在客户端和目标对象之间起到中介的作用,可以增强或控制对目标对象的访问。代理模式的主要...

    设计模式之代理模式Proxy

    代理模式是设计模式中的一种结构型模式,它在对象交互中起到了中介的作用,允许通过代理对象来控制对原对象的访问。代理模式的核心思想是为一个对象提供一个替身,以便增加新的功能或者控制对原对象的访问。这种模式...

    Java设计模式之禅

    《Java设计模式之禅》是一本深入浅出讲解设计模式的书籍,书中不仅包含23种经典设计模式的案例,还详细介绍了设计模式背后的思想和原则,适合初学者以及对设计模式有一定了解的程序员阅读。本书旨在帮助读者理解如何...

    《java设计模式》课后习题模拟试题解答——刘伟.zip

    Java设计模式是软件工程中的一种最佳实践,它总结了在特定场景下解决常见问题的经验,为程序员提供了可重用的解决方案。本资料“《java设计模式》课后习题模拟试题解答——刘伟.zip”主要涵盖了Java设计模式的学习与...

    Java设计模式-代理模式

    总结来说,Java设计模式中的代理模式提供了一种优雅的方式来控制对目标对象的访问,并扩展其功能。动态代理更是使得这一过程更加灵活,降低了代码的维护成本。通过学习和应用代理模式,开发者可以更好地设计和实现...

    《Java设计模式》课后答案-刘伟.rar

    《Java设计模式》是刘伟教授的一本关于设计模式的教材,主要面向高等学校的学生和对Java编程有深入兴趣的开发者。设计模式是软件工程中的一种重要思想,它封装了在特定场景下的问题解决方案,可以提高代码的可读性、...

    23种java设计模式.pdf

    " JAVA 设计模式概述" JAVA 设计模式是指在软件设计过程中,为了提高代码的可维护性、灵活性和可扩展性所使用的一些惯用解决方案。JAVA 设计模式可以分为三种:创建模式、结构模式和行为模式。 1. 创建模式 创建...

    详解设计模式中的proxy代理模式及在Java程序中的实现

    Proxy模式是设计模式中的一种,它提供了一种对对象访问的控制手段,使得在不修改原有对象的基础上,可以通过代理对象来扩展或增强原有对象的功能。在Java编程中,Proxy模式的应用非常广泛,尤其是在处理远程调用、...

    java设计模式视频教程-代理模式.rar

    在这个“java设计模式视频教程-代理模式.rar”压缩包中,包含了一部关于代理模式的视频教程,以及相关的课件和示例代码。 代理模式的核心思想是通过代理类来代理原始对象,为原始对象提供一个替代品或占位符,以...

    java设计模式ppt

    ### Java设计模式详解 在软件开发领域,设计模式是一种被广泛采用的解决方案,用来解决常见的设计问题。设计模式不仅能够帮助开发者写出可复用、可维护的代码,还能提高团队间的沟通效率。以下是对给定文件中提到的...

    JAVA设计模式之结构模式

    这是JAVA设计模式中属于结构模式的部分,包括Flyweight(共享模式)、Bridge(桥模式)、Decorator(装饰模式)、Composite(组合模式)、Adapter(适配器模式)、Proxy(代理模式)、Facade (外观模式)的源代码。其中有些模式中...

    JAVA设计模式-chm版

    Java设计模式是软件开发中的一种最佳实践,它总结了在解决特定问题时程序员们经常采用的有效方法。这个“JAVA设计模式-chm版”资源显然包含了关于Java设计模式的详细信息,便于理解和应用。设计模式是对常见问题的...

Global site tag (gtag.js) - Google Analytics