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设计模式没有什么区别!
仔细分析之后,感觉还是区别蛮大,但是需要实践的道理还是没有变,只有在实践当中,才能够发现应用的实际操作方式。只是一味的模仿、从概念和简单样例中是体会不到模式应用的精髓啊!
<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>这个在上面的评论中也做了介绍。至于具体的应用内容,还需要后续的不断学习中逐步深入、熟悉!~
上一篇: 15.组合模式(Composite Pattern)
下一篇: Mozilla的志愿者开发模式之秘
推荐阅读
-
在Linux中打开了太多文件(Too many open files)的三种解决方法
-
minGw64编译Qt时遇到too many sections问题
-
CentOS Too Many Open Files 解决
-
linux bash中too many arguments问题的解决方法
-
[翻译]:MySQL Error: Too many connections
-
Mysql错误:Too many connections的解决方法
-
mysql连接数设置操作方法(Too many connections)
-
生产问题三:前端显示网络错误,后端日志显示too many connections
-
使用Jetty运行项目报错:Form too large或Form too many keys
-
Nginx failed Too many open files nginxulimit