12-Decorator:too many classes

      呵,从翻译这个标题开始这个模式学习吧:

The use of layered objects to dynamically and transparently add responsibilities to individual objects is referred to as the decorator pattern.--利用多层对象动态、透明地给一个对象添加功能,称之为装饰模式(或者是:
Decorator模式指的是,利用通过层组织起来的多个对象,以动态、透明地方式,来给某单个对象增加新功能,我自己的翻译是:通过将对象分层,然后动态、透明地给一个对象添加功能的应用称之为Decorator模式。真是不好翻译,得好好学习语法了!)

        以下这个参考例子和教材中差不多,但是更形象一些!(图比较酷)
       
http://www.blogjava.net/sterning/archive/2008/01/21/176679.html

 

     实际上,装饰器模式我已经是学习过了,不过没有看懂,都不知道这个有什么作用,尤其是看过的一些例子,不是很有舒服里,尤其是什么打桩、挖坑、钉木板这个例子,很是让我迷惑,感觉和Proxy设计模式没有什么区别!

       仔细分析之后,感觉还是区别蛮大,但是需要实践的道理还是没有变,只有在实践当中,才能够发现应用的实际操作方式。只是一味的模仿、从概念和简单样例中是体会不到模式应用的精髓啊!

       找了一个很好的评论,所谓代理,就是说使用者并不知道被代理对象的存在,被 代理对象的创建和使用均由代理对象控制。Decorator模式下,使用者还是知道真实的被操作对象的,而且知道代理对象的存在。具体到实际的例子中,如 果真实的对象是由客户端显式创建的,则是Decorator模式,如果真实对象不是有客户端显式创建的,则是proxy模式。

 

        以下的评论也挺好的:

     <1> proxy模式指:客户端调用某个类的某个方法,其实是通过proxy来调用的,而客户本身并不知道。比如: 调用某个Shop.order()方法:
客户端的代码看起来如下:
IShop   shop   =   new   Proxy();   //   创建一个代理对象
shop.order();   //   调用代理的方法

Shop类和Proxy类继承自共同的接口IShop,因此客户端引用IShop不能区分是不是Proxy


接口IShop定义商业方法order(),   Shop类实现该方法,而Proxy类也实现该方法,不过实现方法为:

class   Proxy   implements   IShop   {
    public   void   order()   {
        //   先检查:
        if(check())   {
        //   再调用:
        this.shop.order();   //   Proxy对象保持一个Shop类的引用
        //   还可进行扫尾工作
        }
    }
}

这样在客户端根本不需要对每调用一个远程方法作用户权限,身份等检查,客户端针对Proxy编程,Proxy对象对每个方法调用前都可做检查,真正的商业类可以申明为非public,对客户端不可见。


实现Proxy模式需要:

一个接口Interface   定义必要的方法
一个实现类,实现真正的方法,但不做任何用户检查
一个代理类,包含一个实现类的引用,对每个方法调用可进行必要检查
客户端由   Interface   proxy   =   new   Proxy()得到Proxy的引用,却不能区分是 

    Proxy还是真正的实现类,然后对此引用操作。
    Proxy模式的典型应用就是EJB模型。客户端不与EJB对象(相当于实现类)直接作用,而是通过容器(相当于代理)调用EJB对象,容器会对用户调用作检查。

微软的DCOM模型也可看作Proxy模式,RPC可截获客户端对一个远程COM对象的调用,然后真正调用该远程对象并返回结果,客户端根本不知道自己调用的是一个远程对象,而以为是本地对象(因为DCOM调用代码和本地调用是一样的)。


     <2> Decorator 模式是为了增强某个类的功能,典型的应用如java的stream流:
例如java的FileInputStream有read()方法,但不提供缓冲,应用decorator模式将 

     FileInputStream装饰成有缓冲的stream:
    InputStream   in   =   new   BufferedInputStream(new   FileInputStream( "C:\\1.txt "));

     客户端调用in.read()不知道实际的read功能是由哪个类具体提供的,也分辨不出in的具体类型,因为只有对接口的引用。这种是透明的装饰模式。

      透明装饰模式的关键是客户端只针对接口编程(InputStream是抽象类也是BufferedInputStream和FileInputStream的超类)。

      不透明的装饰模式:装饰类可以提供额外的方法来增强某些功能,例如:

FileInputSteam没有readLine()而BufferedInputStream有readLine(),为了使用额外的功能,客户端不得不把in的类型申明为:
      BufferedInputStream   in   =   new   BufferedInputStream(new     

        FileInputStream( "C:\\1.txt "));
优点是可以使用新的额外方法:in.readLine()
缺点是客户端必须确切知道装饰类提供哪些额外的方法。


//实际的做法就是:好好看看源码...

以 java.io.InputStream 为例,下图是类结构图:


    InputStream是一个抽象类,是所有数据形式为字节的输入流的父类,为基于字节的数据输入定义了基本操作方法。实际 上,InputStream的子类大部分都没有增加任何其他的接口函数(在上面的类结构图中就可以发现),因此在看InputStream子类的时候,我 们主要学习其构造函数。

    Java I/O中是如何采用Decorator(装饰)模式的呢?下面为大家详细说明,看到FilterInputStream类(也就前面说的过滤流,后面你会 发现更多的过滤流),你是否发现了?对,就是FilterInputStream类,她就相当于Decorator(装饰)模式中的Decorator 类,而且的BufferedInputStream、DataInputStream、PushbackInputStream则相当于是 ConcreateDecorator,如下图所示:

   

    那么Java I/O中到底是如何使用的了?Decorator(装饰)模式的主要意图是:动态地给一个对象添加一些额外的职责,这句话很抽象,我们结合Java I/O举个具体的例子:比如说我们读取文件,首先打开文件获取到File,然后我们再创建一个FileInputStream,然后读取文件。读取文件是 一个很费时的操作,尤其是需要多次的读写文件。

    例如,BufferedInputStream实现了对数据读取的缓冲机制,通过FileInputStream来 读取数据,BufferedInputStream将已经读取的数据存储到缓冲区,BufferedInputStream相当于对 FileInputStream进行了“装饰”。

     File file = new File(“c:\\moandroid.txt”,true);
     InputStream is = new BufferedInputStream(new FileInputStream(file));

    如果没有应用Decorator模式的话,就只能应用:

     InputStream is =new FileInputStream(file);

    这样就失去了缓存处理操作,增加了I/O等待时间,没有获得很高的效率.....

 

更多解析可以查看:http://apps.hi.baidu.com/share/detail/51853225

 

      综合,自己学习的过程,用意去区别各种模式的不同是需要的,但是,更重要的是在实际应用中取提取这种模式案例,这个是学习的很好途径。具体到Decorator和Proxy的区别,<1>Decorator是需要功能上的增强,根据用户的具体应用需求来添加各种功能,这在客户端应用时很是方便。要是透明处理,直接就是返回了接口部分。 对于后者来说,完成的任务主要是在安全等方面,将具体逻辑模块和验证模块解耦。如果你非要在这里加上一些增强型功能(很多时候是不必要的),也是可以的。所以,更具不同应用场景来区分设计模式也是有道理的!<2>这个在上面的评论中也做了介绍。至于具体的应用内容,还需要后续的不断学习中逐步深入、熟悉!~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值