• [转]转个经典的帖子:说故事学设计模式之Java动态代理模式


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

    请看代码

    在原有代码的基础上我们做了这些宽展:

    /*
    *汽车批发商
    *这样我们的代码中就有了电脑和汽车这两个批发商
    */

    public interface Cat {
        
    public void buyCat(String name);
    }

    /*
    *劳斯莱斯汽车公司
    */

    public class RollsRoyce implements Cat {

        
    public void buyCat(String name) {
            
            System.out.println(name
    +"  劳斯莱斯公司产品!");
        }


    }

    /*
    *所有行业代理商
    *有了它我们的客户可以通过他买个各种产品
    */

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.logging.Level;
    import java.util.logging.Logger;

    public class AllthingsProxy implements InvocationHandler {

        
    private Logger logger=
            Logger.getLogger(
    this.getClass().getName());
        
        
    private Object allthings;
        
        
    //实现对象绑定
        public Object bind(Object allthings){
            
            
    this.allthings = allthings;
            
            
    //这里传入newProxyInstance的参数分别是 目标object
            
    //(Lianxiang,Sanxing),interface(Computer),AllthingsProxy
            return Proxy.newProxyInstance(allthings.getClass().getClassLoader(),
                                        allthings.getClass().getInterfaces(), 
    this);
        }

        
        
    public Object invoke(Object proxy, Method method, Object[] args)
                
    throws Throwable {
            
            Object result 
    = null;
            
            
    try{
            log(
    "method starts " + method);
            
            result
    =method.invoke(allthings, args);

            logger.log(Level.INFO , 
    "method ends " + method);
            
            }
    catch(Exception e){
                log(e.toString());
            }

            
            
    return result;
        }

        
        
    private void log(String msg){
            logger.log(Level.INFO,msg);
        }


    }


    在测试类BuyAllThings中,我们通过bing方法绑定对象(所要买的东西),让代理商了解到,客户想买什么?
    (这里重在了解模式,具体方法的实现如不了解请自行查询API文档)


    /*
    *三个客户两个买电脑一个买汽车
    *他们找到同个代理商
    */

    public class BuyAllThing {

        
    public static void main(String[] args) {
            
            AllthingsProxy allthingsproxy 
    = new AllthingsProxy();
            
            Computer SanxingProxy
    =(Computer)allthingsproxy.bind(new Sanxing());
            
            SanxingProxy.buyComputer(
    "我想买一台三星电脑");
            
            Computer lianxiangProxy
    =(Computer)allthingsproxy.bind(new Lianxiang());
            
            lianxiangProxy.buyComputer(
    "我想买一台联想电脑");
            
            Cat RollsRoyceProxy
    =(Cat)allthingsproxy.bind(new RollsRoyce());
            
            RollsRoyceProxy.buyCat(
    "我想买一辆劳斯莱斯汽车");

        }


    }

    执行结果

    我想买一台三星电脑  三星电脑公司产品!
    我想买一台联想电脑  联想电脑公司产品!
    我想买一辆劳斯莱斯汽车  劳斯莱斯公司产品!
    2007-8-9 13:08:41 com.lusm.spring.AllthingsProxy log
    信息: method starts 
    public abstract void com.lusm.spring.Computer.buyComputer(java.lang.String)
    2007-8-9 13:08:42 com.lusm.spring.AllthingsProxy invoke
    信息: method ends 
    public abstract void com.lusm.spring.Computer.buyComputer(java.lang.String)
    2007-8-9 13:08:42 com.lusm.spring.AllthingsProxy log
    信息: method starts 
    public abstract void com.lusm.spring.Computer.buyComputer(java.lang.String)
    2007-8-9 13:08:42 com.lusm.spring.AllthingsProxy invoke
    信息: method ends 
    public abstract void com.lusm.spring.Computer.buyComputer(java.lang.String)
    2007-8-9 13:08:42 com.lusm.spring.AllthingsProxy log
    信息: method starts 
    public abstract void com.lusm.spring.Cat.buyCat(java.lang.String)
    2007-8-9 13:08:42 com.lusm.spring.AllthingsProxy invoke
    信息: method ends 
    public abstract void com.lusm.spring.Cat.buyCat(java.lang.String)

    我们可以任意的增加代理商的业务,比如,叫他代理电器,食物......,我们看到我们不需要更改原有的代码。这是动态代理带来的好处!

    那我们的AllthingsProxy是怎么作到动态代理的呢?

    AllthingsProxy宽展了InvocationHandler并实现了里面的代理方法,返回一个Object对象,

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

    来实现对汽车,电脑这些批发商的动态代理(代理商同过它 代理所有行业)。

    AllthingsProxy中的bind实现了客户和代理商间的通信(通过它代理商知道客户想要买什么)

    这和我们 BuyAllThing 测试类main中

    代理对象=(绑定对象)allthingsproxy.bind(绑定对象(客户想买的东西))

    想对应。

             呵呵 ,讲完了!也许有的朋友看不懂这里在说什么? 不必着急,学习都需要过程,等你的学习到某个阶段的时候,回头想想,也许认识就会加深许多,本人觉得Java是比较高级的语言,自身的发展也只直遵循着软件设计优化(代码重用)方向发展,重视设计思想,而不是去改变语言的语法或接口api,这是许多语言所缺乏的,如一个在VC6中编写的代码,拿到Visual Studio2005,Visual Studio2008去运行很容易出现问题。

           也许你并不清楚我在说什么?但是这一切会在你的Spring学习中渐渐清楚起来!

           以后的代码可能需要必要的IDE才能使用,本人使用的是:
           MyEclipse6.0M1+Eclipse3.3 
           数据库用的是:
          Oralce10g或者Mysql6.0

          祝你好运气!!!
  • 相关阅读:
    Git设置HTTP/HTTPS代理服务器
    队列(Queue)顺序存储C语言实现
    二叉树前序序列和中序序列转为后序序列
    CFileDialog对话框中,如何修改对话框标题
    轻型读写锁 Slim Reader/Writer (SRW) Locks
    PC lint -sem 用法示例
    C# Linq 取得两个列表的交集
    wpf datagrid row的命中测试
    C# Unit Test 备注
    DataGrid 滚动特定的行或者列
  • 原文地址:https://www.cnblogs.com/redcoatjk/p/3562426.html
Copyright © 2020-2023  润新知