zoukankan      html  css  js  c++  java
  • 设计模式--Proxy

    转自:http://blog.csdn.net/dan_xp/article/details/1820852

    最近一直在看java的设计模式 ,感觉印象最深刻的就是"面向接口编程",在java中,尽量多定义接口,因为设计的最重要的目的就是应对各 种变化,而接口本身就是一种变化着的Class的直接反映,通过实现特定接口的各种具体类,达到应对变化的目的,下面以Proxy模式为例:

    Proxy的模式最主要的目的,原有的类对象由于某种原因不能访问,需要通过一个新的类来间接地去实现,这个新的类就称为代理类,举个例子说明,老王买/卖鱼的例子
    public class SellFisher {
        
    public int sellFish() {
            System.out.println(
    "my fish is delicious!!");
            
    return 10;
        }

    }
    这是一个具体的卖鱼类,表示鱼10元/斤,如果这个类被用到系统中的时候,系统应对变化的灵活性就会大打折扣,请看如下:
    public class SellFishSystem {
        
    private SellFisher sellfish;
                         
    //...
        public void sellFish() {
            sellfish.sellFish();
        }

    }
    如果以后鱼的价格变化,或者具体的卖鱼方法发生变化,就必须修改已经有的SellFisher的sellFish()的代码,这个情况
    使得系统的可扩展性降低,我们肯定会想到解决方案了,定义一个接口,请看代码:
    interface SellFisher {
        
    int sellFish();
    }

    public class SellFishSystem {
        
    private SellFisher sellfish;
        
    public void sellFish() {
            sellfish.sellFish();
        }

    }
    我们所做的变化,只是把SellFisher从Class提升到Interface,这个时候好处自然很明显了,这个SellFisher本身就代表
    了一种不确定,变化.大家在做开发的时候,阅读源代码的时候,肯定遇到过这种情况,总是跟踪类的对象看代码实现,如果发现了接口变量,就会比较 郁闷,得了解它的具体实现类是什么,这个具体实现类的变化通常就可以应对需求的变化,系以及系统扩展.请看上例子,如果鱼的价格变化,或者具体的卖鱼方法 发生变化,我们只需要新增加SellFisher的实现,
    而不必修改已有的代码,对此我的理解是对系统来说,新增加一个类的代码风险要大大低于对已有类的代码的修改.我觉得这个也是设计模式的立足点吧(如果你喜欢修改已有代码,那么设计模式就没有多大意义了)
    言归正传,有了上面的知识准备,我们接上面的例子来解释Proxy的模式就简单多了,比如现在鱼的价格变化,卖鱼的提示也发生变化了,我们需要一个新的Proxy类来实现
    interface SellFisher {
        
    int sellFish();
    }

    public class ConcreteSellFisher implements SellFisher {

        
    public int sellFish() {
             System.out.println(
    "my fish is delicious!!");
             
    return 10;
        }

    }

    public class ProxySellFisher implements SellFisher {

        
    private SellFisher sell;
        
    public ProxySellFisher(SellFisher sell) {
            
    this.sell = sell;
        }
        
    public int sellFish() {
            System.out.println(
    "the fish price higher");
            
    return sell.sellFish()+10;
        }

    }
    看上面,这个是Proxy模式的代码例子实现,我们现在在SellFishSystem 使用ProxySellFisher来卖鱼了,由ProxySellFisher再调用原来的ConcreteSellFisher类.具体的一些特征总结为:
    1.有个代理类Proxy(和原来的实现类继承同一接口),该类里引用了原来的具体功能实现类(这里是ConcreteSellFisher)
    2.重写实现方法,加一些新的变化的元素(比如鱼的价格上涨)
    JDK里的Proxy类也实现了这个模式,只不过它叫动态代理,因为它的代理类变成了InvocationHandler了,执行的方法
    是invoke了,从而变得更加灵活了,请看代码
    public class ProxySellFisher implements InvocationHandler {

        
    private SellFisher sell;
        
    public ProxySellFisher(SellFisher sell) {
            
    this.sell = sell;
        }
        
    public Object invoke(Object obj, Method method, Object[] args) throws Throwable {
            System.out.println(
    "the fish price higher");
            
    return (Integer)method.invoke(sell, args)+10;
        }

    }


    public class ClientTest {
        
    public static void main(String args[]) {
            SellFisher s 
    = new ConcreteSellFisher();
            InvocationHandler p 
    = new ProxySellFisher(s);
            Object obj 
    = Proxy.newProxyInstance(s.getClass().getClassLoader(), s.getClass().getInterfaces(), p);
            ((SellFisher)obj).sellFish();
        }
    }
    请注意,invoke(Object obj,Method method,Object[] args),这里的第一个参数obj其实可以看作没有用处的,不知道jdk为什么要把它也当作一个参数放这里,methd.invoke()方法,需要把 原来的具体实现类作为参数传递进去,method.invoke(obj,args)相当于obj.method(args)
    总结,从设计模式的角度讲,大家以后编程中,尽量要面向接口,更通俗一点就是,一个类中使用的别的对象成员变量,最好定义成接口的变量而不是实际实现类的变量
  • 相关阅读:
    JavaWeb之Servlet的生命周期
    Java之HashMap和HashTable的区别
    Java之使用中间缓存变量机制
    哪项技术可以用在WEB开发中实现会话跟踪实现?
    Spring的简单定时任务的实现
    Java解决No enclosing instance of type PrintListFromTailToHead is accessible问题
    StringBuffer和StringBuilder的区别
    论文阅读笔记:《Generating Question-Answer Hierarchies》
    python学习笔记(十)——正则表达式和re模块
    Python学习笔记(九)——字符串
  • 原文地址:https://www.cnblogs.com/bicabo/p/3718235.html
Copyright © 2011-2022 走看看