转自:http://www.riabook.cn/doc/designpattern/
Design Pattern: Proxy 模式(二)
延续 Proxy模式(一) 的议题,来看看实现代理的两种方式:Static Proxy与Dynamic Proxy。严格来说这是属于模式的实现方式,不过藉由实例可以更了解Proxy模式的应用。
先来看个例子,这个例子是记录(log)动作,程式中很常需要为某些动作或事件作下记录,以便在事后检视或是作为除错时的资讯,一个最简单的例子如下:
HelloSpeaker.java
import java.util.logging.*; public class HelloSpeaker { private Logger logger = Logger.getLogger(this.getClass().getName()); public void hello(String name) { logger.log(Level.INFO, "hello method starts...."); System.out.println("Hello, " + name); logger.log(Level.INFO, "hello method ends...."); } }
HelloSpeaker在执行hello()方法时,您希望能记录该方法已经执行及结束,最简单的作法就是如上在执行的前后加上记录动作,然而 Logger介入了HelloSpeaker中,记录这个动作并不属于HelloSpeaker,这使得HelloSpeaker增加了非业务上需要的逻 辑在当中。
想想如果程式中这种记录的动作到处都有需求,上面这种写法势必造成必须复制记录动作的程式码,使得维护记录动作的困难度加大。如果不只有记录动作,有一些 非物件本身职责的相关动作也混入了物件之中(例如权限检查、事务管理等等),会使得物件的负担更形加重,甚至混淆了物件的职责,物件本身的职责所占的程式 码,或许远小于这些与物件职责不相关动作的程式码。
怎么办,用下面的方法或许好一些,先定义一个介面,然后实作该介面:
IHello.java
public interface IHello { public void hello(String name); }
HelloSpeaker.java
public class HelloSpeaker implements IHello { public void hello(String name) { System.out.println("Hello, " + name); } }
接下来实作一个代理物件HelloProxy:
HelloProxy.java
import java.util.logging.*; public class HelloProxy implements IHello { private Logger logger = Logger.getLogger(this.getClass().getName()); private IHello helloObject; public HelloProxy(IHello helloObject) { this.helloObject = helloObject; } public void hello(String name) { logger.log(Level.INFO, "hello method starts...."); helloObject.hello(name); logger.log(Level.INFO, "hello method ends...."); } }
执行时可以如此:
IHello helloProxy = new HelloProxy(new HelloSpeaker());
helloProxy.hello("Justin");
代理物件HelloProxy将代理真正的HelloSpeaker来执行hello(),并在其前后加上记录的动作,这使得 HelloSpeaker在撰写时不必介入记录动作,HelloSpeaker可以专心于它的职责。
这是Static Proxy的基本范例,然而如您所看到的,代理物件的一个介面只服务于一种类型的物件,而且如果要代理的方法很多,势必要为每个方法进行代理, Static Proxy在程式规模稍大时就必定无法胜任。
Java在JDK 1.3之后加入协助开发Dynamic Proxy功能的类别,我们不必为特定物件与方法撰写特定的代理,使用Dynamic Proxy,可以使得一个handler服务于各个物件,首先,一个handler必须实现 java.lang.reflect.InvocationHandler:
LogHandler.java
import java.util.logging.*; import java.lang.reflect.*; public class LogHandler implements InvocationHandler { private Logger logger = Logger.getLogger(this.getClass().getName()); private Object delegate; public Object bind(Object delegate) { this.delegate = delegate; return Proxy.newProxyInstance( delegate.getClass().getClassLoader(), delegate.getClass().getInterfaces(), this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = null; try { logger.log(Level.INFO, "method starts..." + method); result = method.invoke(delegate, args); logger.log(Level.INFO, "method ends..." + method); } catch (Exception e){ logger.log(Level.INFO, e.toString()); } return result; } }
InvocationHandler的invoke()方法会传入被代理物件的方法名称与执行参数实际上要执行的方法交由method.invoke (),并在其前后加上记录动作,method.invoke()传回的物件是实际方法执行过后的回传结果。
Dynamic Proxy必须宣告介面,实作该介面,例如:
IHello.java
public interface IHello { public void hello(String name); }
HelloSpeaker.java
public class HelloSpeaker implements IHello { public void hello(String name) { System.out.println("Hello, " + name); } }
java.lang.reflect.Proxy的newProxyInstance()依要代理的物件、介面与handler产生一个代理物件,我们可 以使用下面的方法来执行程式:
LogHandler logHandler = new LogHandler();
IHello helloProxy = (IHello) logHandler.bind(
new HelloSpeaker());
helloProxy.hello("Justin");
LogHandler不在服务于特定物件与介面,而HelloSpeaker也不用插入任何有关于记录的动作,它不用意识到记录动作的存在。
相关推荐
Proxy 模式学习代码,包括静态代理,动态代理,cglib等
到工厂方法到抽象工厂,这几种都带有“工厂”的模式,总是容易叫人迷糊,我仔细研究了下,然后用简单的例子做类比,列出了自己的通俗理解和比较,大部分是自己的体会,感觉理的比较清楚,末尾提了下Proxy模式。
设计模式C++学习之代理模式(Proxy)
23种设计模式之十二(结构型模式)Proxy模式
代码仅供参考学习 。
JAVA Proxy 代理模式
C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式)
C#面向对象设计模式纵横谈(13):Proxy 代理模式(结构型模式) (Level 300)
MySQL数据库中间件:基于C语言开发,包含59个文件,包括22个C源文件...该项目是一个分布式MySQL数据库中间件,采用Proxy模式设计,基于核心业务对象切分,旨在提供高效的数据库查询和处理能力,适用于分布式系统环境。
java.proxy,代理模式源码,设计模式,apache开源项目源码commons-proxy-1.0-src 各种代理模式操作的工具类源码以及代理模式案例源码,你会从中得到意想不到的效果! apache开源组织开发的开源项目源码,其优良的代码...
代理模式java代码 Proxy(4) 开发宝典......
Proxy代理模式的经典实例(很有面向对象思想哦)。快速学会Proxy代理模式.
Proxy Pattern 代理模式 采用JAVA实现,可以下载看看。
Android设计模式之代理模式(Proxy Pattern)
在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。
2、代理模式(Proxy) 用意:为其它对象提供一种代理以控制对这个对象的访问
1. 打开Chrome -> 自定义及控制按钮(右上角) -> 更多工具 -> 扩展程序 (有可能需要打开开发者模式) 2. 拖拽Proxy-SwitchyOmega_2_5_15_0.crx到扩展管理界面 3. 安装 原始安装路径: ...
我自己用eclipse写的java代码,可以直接用eclipse导入,也可以直接用java -jar proxy_sample.jar执行 代码量很小,尽量通过注释进行说明 本例实现了InvocationHandler...在研究代理模式(Proxy模式)的朋友可以交流一下
详解设计模式中的proxy代理模式及在Java程序中的实现共14页.pdf.zip