您的位置:首页 > 编程语言 > Java开发

用Java动态代理实现委托模式

2010-04-07 09:10 591 查看
委托模式是软件设计模式中的一项基本技巧。在委托模式中,有两个对象参与处理同一个请求,接受请求的对象将请求委托给另一个对象来处理。委托模式是一项基本技巧,许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式。委托模式使得我们可以用聚合来替代继承,它还使我们可以模拟mixin。
“委托”在C#中是一个语言级特性,而在Java语言中没有直接的对应,但是我们可以通过动态代理来实现委托!代码如下:

1.import java.lang.reflect.InvocationHandler;
2.import java.lang.reflect.Method;
3.import java.lang.reflect.Proxy;
4./*
5. * @author Liusheng
6. * 实现“委托”模式,用户需要实现InvocationHandler接口;
7. * 参考:http://www.uml.org.cn/j2ee/200411036.htm
8. */
9.public abstract class Delegator implements InvocationHandler {
10.    //RelegateTo针对每个对象都要生成一个实例,因而非Static的log,代价比较高。
11.    //protected Log _log = LogFactory.getLog(this.getClass());
12.    //private static Log _log = LogFactory.getLog(RelegateTo.class);
13.    //--------------------------------------------
14.    protected Object obj_orgin = null;  //原始对象
15.    protected Object obj_proxy = null;  //代理对象
16.    //--------------------------------------------
17.    public Delegator()  {
18.        //空
19.    }
20.    public Delegator(Object orgin){
21.        this.createProxy(orgin);
22.    }
23.    //--------------------------------------------
24.    protected Object createProxy(Object orgin) {
25.        obj_orgin = orgin;
26.        obj_proxy = Proxy.newProxyInstance(
27.                orgin.getClass().getClassLoader(),  //加载器
28.                orgin.getClass().getInterfaces(),   //接口集
29.                this);  //委托
30.        //_log.debug("# 委托代理:"+obj_proxy);
31.        return obj_proxy;
32.    }
33.    protected Object invokeSuper(Method method, Object[] args)
34.    throws Throwable {
35.        return method.invoke(obj_orgin, args);
36.    }
37.    //--------------实现InvocationHandler接口,要求覆盖------------
38.    public Object invoke(Object obj, Method method, Object[] args)
39.    throws Throwable {
40.        // 缺省实现:委托给obj_orgin完成对应的操作
41.        if (method.getName().equals("toString")) {  //对其做额外处理
42.            return this.invokeSuper(method, args)+"$Proxy";
43.        }else {     //注意,调用原始对象的方法,而不是代理的(obj==obj_proxy)
44.            return this.invokeSuper(method, args);
45.        }
46.    }
47.}


下面的代码,则是作为一个委托的例子,实现Map的功能。

1.import java.io.IOException;
2.import java.lang.reflect.Method;
3.import java.util.Hashtable;
4.import java.util.Map;
5.import org.apache.commons.logging.Log;
6.import org.apache.commons.logging.LogFactory;
7.import com.bs2.core.UtilLog;
8./**
9. * @author Liusheng
10. * 本代码主要用于演示RelegateTo的使用方法
11. */
12.public class Delegator4Map extends Delegator {
13.    private static Log _log = LogFactory.getLog(Delegator4Map.class);
14.    private Map orginClass = null;  //原始对象
15.    private Map proxyClass = null;  //代理对象
16.
17.    public Map getOrgin() { return orginClass;  }
18.    public Map getProxy() { return proxyClass;  }
19.
20.    public Delegator4Map(Map orgin) {
21.        super(orgin);
22.        orginClass = orgin;
23.        proxyClass = (Map)super.obj_proxy;
24.    }
25.    public Object invoke(Object obj, Method method, Object[] args)
26.    throws Throwable {
27.        if (method.getName().equals("size")) {  //修改close处理逻辑
28.            _log.debug("原始 size()="+super.invoke(obj, method, args));
29.            Object res2 = new Integer(-1);
30.            _log.debug("修改 size()="+res2);
31.            return res2;
32.        }else {
33.            return super.invoke(obj, method, args);
34.        }
35.    }
36.    public static void main(String[] args) throws IOException {
37.        UtilLog.configureClassPath("resources/log4j.properties", false);
38.        Delegator4Map rtm = new Delegator4Map(new Hashtable());
39.        Map m = rtm.getProxy();
40.        m.size();
41.        _log.debug("代理:"+m.toString());
42.    }
43.}


注意:UtilLog仅仅是用于配置log4j属性文件位置,如果log4j.properties就在缺省的运行路径下,则无需单独配置。或者用System.out输出来替代_log输出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: