首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

温习:代理模式

2012-12-23 
复习:代理模式??? 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,如图1所示。代理

复习:代理模式

??? 代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,如图1所示。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。


温习:代理模式

图1:Proxy模式

?

按照代理类的创建时期,代理类可分为两种。

静态代理类:由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理类:在程序运行时,运用反射机制动态创建而成。

?

静态代理类的实现:

?

1. 定义一个IService接口

package cn.lettoo.proxy;public interface IService {    void execute();}

?

2. 具体的实现类:

package cn.lettoo.proxy;public class PrintService implements IService {    public void execute() {        System.out.println("The Print Service works.");    }}

?

3. 代理类:

package cn.lettoo.proxy;public class PrintServiceProxy implements IService {    IService printSerivce;    public PrintServiceProxy(IService service) {        this.printSerivce = service;    }    public void setPrintSerivce(IService printSerivce) {        this.printSerivce = printSerivce;    }    public void execute() {        this.beforePrint();        this.printSerivce.execute();        this.afterPrint();    }    private void beforePrint() {        System.out.println("Before print.");    }    private void afterPrint() {        System.out.println("Before print.");    }}

??? 代理类的execute()方法只是调用了被代理的Service的execute方法,被代理的Service通过构造函数或者set的方式被注入到代理对象中。同时,代理对象也有一些自己的代理方法,如本例中在被代理类的execute()方法调用前后加上自己的方法。

?

4. 客户调用代码:

package cn.lettoo.proxy;public class Client {    public static void main(String[] args) {        IService service = new PrintService();        IService proxy = new PrintServiceProxy(service);        proxy.execute();    }}

?

//创建InvocationHandler对象InvocationHandler handler = newMyInvocationHandler(...);//创建动态代理类,IService是被代理的接口Class proxyClass = Proxy.getProxyClass(IService.class.getClassLoader(), new Class[] { IService.class });//创建动态代理类的实例IService proxyService = (IService) proxyClass.getConstructor(new Class[] { invocationHandler.class }).newInstance(new Object[] { handler });

方法2:

//创建InvocationHandler对象InvocationHandler handler = newMyInvocationHandler(...);//直接创建动态代理类的实例IService serviceProxy = (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class },handler);

?

InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法:

Object invoke(Object proxy,Method method,Object[] args) throws Throwable

?

代码实现:

1. 写一个ServiceFactory,用于生成代理对象

package cn.lettoo.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ServiceFactory {    public static IService getServiceProxy(final IService service) {        InvocationHandler handler = new InvocationHandler() {            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                beforePrint();                Object result = method.invoke(service, args);                afterPrint();                return result;            }        };        return (IService) Proxy.newProxyInstance(IService.class.getClassLoader(), new Class[] { IService.class },                                                 handler);    }        private static void beforePrint() {        System.out.println("Before print.");    }    private static void afterPrint() {        System.out.println("Before print.");    }    }

?

2. 客户端代码:

package cn.lettoo.proxy;public class Client {    public static void main(String[] args) {        IService service = new PrintService();                IService proxy = ServiceFactory.getServiceProxy(service);                proxy.execute();    }}

?

package cn.lettoo.proxy;public class AnotherService implements IService { public void execute() { System.out.println("I am another service."); }}

?

? ? 现在客户端只要这样写:

    public static void main(String[] args) {        IService service = new AnotherService();                IService proxy = ServiceFactory.getServiceProxy(service);                proxy.execute();    }

?

运行结果Before print.
I am another service.
Before print.?

??? 可以看到,不需要单独再为AnotherService写一个代理类了,动态代理类会帮助我们去实现的。

热点排行