http://hxraid.iteye.com/blog/432658
继承是OOP程序设计的一大特点,但其实对于很多复杂问题来说,利用继承关系处理问题往往具有很高的耦合性,不利于代码的维护。利用组合很大程度上可以做到降耦。多用组合,少用继承是OOP设计的重要思想。
装饰者模式给我们提出了一个好的OOP设计原则:类应该对扩展开放,对修改关闭 。
这句话的意思就是,如果问题发生改变,衡量一个好的设计标准就是:你不需要修改类中的代码,只需要扩展新类来适应新的行为。
《Head First Design Patterns》对装饰者模式说的很清楚。这里稍微注意几点:
(1) 装饰者和被装饰者必须具有相同的超类型。
(2) 装饰者即可以包装被装饰者,也可以包装装饰者。往往利用多层包装来达到目的。
(3) 装饰者中组合了被装饰者对象,这是装饰类的关键特征。正是由于这种组合,使得我们能够随心所欲的通过嵌套装饰来动态扩展行为。
在java类库中的IO流就是用装饰者模式设计的。JDK5.0中60多个IO流类组成了四大家族:InputStream,OutputStream,Reader,Writer。
InputStream/OutputStream是对字节序列进行操作的抽象类。
Reader/Writer是基于Unicode代码单元进行操作的抽象类。
这四大家族中大量的类都具有自己不同的功能,要做到方便的完成各种输入输出行为。必须组合使用这些类,装饰者模式是再好不过的设计了。那么IO类库如何实现装饰者模式的,我们看看几个类的部分源码:
Java代码
//InputStream:字节序列输入类鼻祖
public abstract class InputStream implements Closeable {
//最基本的读取字节的抽象方法,供子类扩展。
public abstract int read() throws IOException;
}
//InputStream:字节序列输入类鼻祖
public abstract class InputStream implements Closeable {
//最基本的读取字节的抽象方法,供子类扩展。
public abstract int read() throws IOException;
}
Java代码
//FileInputStream: 读取文件中的字节流类 继承InputStream
public class FileInputStream extends InputStream{
//构造器
public FileInputStream(String name) throws FileNotFoundException {
//.......
}
//本地方法,与操作系统低层交互的具体读入方法
public native int read() throws IOException;
}
//FileInputStream: 读取文件中的字节流类 继承InputStream
public class FileInputStream extends InputStream{
//构造器
public FileInputStream(String name) throws FileNotFoundException {
//.......
}
//本地方法,与操作系统低层交互的具体读入方法
public native int read() throws IOException;
}
Java代码
//FilterInputStream: 过滤流类,起装饰器作用,用于对输入装配各种功能
public class FilterInputStream extends InputStream {
//用于记录被装饰者,也就是需要装配新功能的InputStream对象
protected volatile InputStream in;
//构造装饰器
protected FilterInputStream(InputStream in) {
this.in = in; //设置需要被包装InputStream对象
}
//读入字节
public int read() throws IOException {
return in.read();
}
}
//FilterInputStream: 过滤流类,起装饰器作用,用于对输入装配各种功能
public class FilterInputStream extends InputStream {
//用于记录被装饰者,也就是需要装配新功能的InputStream对象
protected volatile InputStream in;
//构造装饰器
protected FilterInputStream(InputStream in) {
this.in = in; //设置需要被包装InputStream对象
}
//读入字节
public int read() throws IOException {
return in.read();
}
}
Java代码
//BufferedInputStream: 使输入流具有缓冲功能,是一种可以装配缓冲功能的装饰器,继承FilterInputStream
public class BufferedInputStream extends FilterInputStream {
//构造器
public BufferedInputStream(InputStream in) {
this(in, defaultBufferSize); //in就是被装配缓冲功能的InputStream
}
}
//BufferedInputStream: 使输入流具有缓冲功能,是一种可以装配缓冲功能的装饰器,继承FilterInputStream
public class BufferedInputStream extends FilterInputStream {
//构造器
public BufferedInputStream(InputStream in) {
this(in, defaultBufferSize); //in就是被装配缓冲功能的InputStream
}
} 这四个类同属于InputStream家族,他们就是一个经典的装饰器模式设计。其中
InputStream 具有读入功能的抽象被装饰器。
FileInputStream 具有读入文件功能的具体被装饰器。
FilterInputStream 具备装饰器的抽象意义。
BufferedInputStream 具有具体功能(缓冲功能)的装饰器。
这个时候后我想设计一个具有缓冲功能的读取文件中的字节的行为:
Java代码
public void IOTest{
//缓冲装饰器包装文件字节输入流
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("C://decorator.txt"));
//读取内容
bis.read();
}
public void IOTest{
//缓冲装饰器包装文件字节输入流
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("C://decorator.txt"));
//读取内容
bis.read();
} IO类库中还有很多其他的装饰器,比如处理基本数据类型的DataInputStream,处理ZIP文件流的ZipInputStream,等等。只要我们想的到的行为,都可以用这些装饰器包装组合来完成。就这一点,装饰器绝对是Perfect。
但是装饰器模式也有一个算不上缺点,但也不太好的地方。这种设计常常造成大量的小类存在,数量之大可能会给类消费者很大的困扰。是吧!学习Java的IO流是不是特痛苦呀......
备注:JDK中的集合类库也使用了装饰者模式,在《集合类库(六):集合类的相互包装 》中有详细介绍。
分享到:
相关推荐
支持Fastify版本3.x安装npm i fastify-socket.io用法需要fastify-socket.io并将其注册为任何其他插件,它将添加一个io装饰器。 const fastify = require ( 'fastify' ) ( )fastify . register ( require ( 'fastify...
这也是我们在第 10 节中讲的不推荐使用继承的原因。基于装饰器模式的设计方案在第 10 节中,我们还讲到“组合优于继承”,可以“使用组合来替代继承”。针对刚刚的
Java IO体系结构看似庞大复杂,其实有规律可循,要弄清楚其结构,需要明白两点: 1. 其对称性质:InputStream 与 OutputStream, Reader 与 Writer,他们分别是一套字节输入-...2. 原始处理器(适配器)与链接流处理器(装饰器)
装饰器类 in = new 装饰器类(fis); BufferedReader in = new BufferedReader(new FileReader("Car.java")); BufferedWriter out = new BufferedWriter(new FileReader("Car2.java")); 利用缓冲流读取的时候是逐行...
java IO 流全面总结 InputStream输入流继承关系: 采用了装饰器模式。
实际上Java提供的工具包中,IO相关工具就普遍大量使用了装饰器模式,例如充当装饰功能的IO类如BufferedInputStream等,又被称为高级流,通常将基本流作为高级流构造器的参数传入,将其作为高级流的一个关联对象,...
仅2kb min gzip React性属性$socket.connected和$socket.disconnected 侦听和发出组件内部的socket.io事件在socket.io事件上自动调度多个命名空间的Vuex模块中的动作和变异良好的TypeScript支持(装饰器和键入) ...
ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。 2.输出字节流OutputStream IO 中输出字节流的继承图可见上图,可以看出: OutputStream 是所有的输出字节流的父类,它是一个...
特别是怎样在类中使用装饰器,怎样给装饰器传递额外的参数。 装饰器 vs 装饰器模式 Decorator模式是一个面向对象的设计模式,它允许动态地往现有的对象添加行为。当你装饰了一个对象,在某种程度上,你是在独立于同...
字母装饰器 这是RecyclerView.ItemDecorator的实现,用于在左侧显示字母。 它基于Google的Contatcs应用程序。 你能做什么呢? 您可以在装饰器构造函数中设置左填充。 如果将其设置为0,将从项目视图范围的左边缘...
socket.disconnected侦听和发出组件内的socket.io事件自动调度动作和突变在socket.io事件上的多个具有命名空间的Vuex模块中,具有良好的TypeScript支持(装饰器和键入),可与任何版本的socket.io-client一起使用。
java io流里面使用到了很多的设计模式,最典型的就是装饰模式,还有命令模式,下面分两部分来讲Java IO文件过滤器对命令设计模式的使用,一起看看吧
类方法调用日志装饰器 描述 装饰器,用于简单多彩的日志类方法调用(在Chrome,FF和Node中),返回的结果和可能的错误。 用于Node。 安装 yarn add cmild 测验 yarn test:jest # Runs Jest with coverage collection...
11. 解释 Python 中的装饰器的概念和用途。 12. 如何处理并发编程中的线程和进程? 13. 解释 Python 中的多线程和多进程的区别和应用场景。 14. 什么是装饰器?如何自定义一个装饰器? 15. 解释 Python 中的迭代器和...
字体和文件使用public文件夹更改HTML 在模块系统之外添加资产何时使用public文件夹使用全局变量添加引导程序使用自定义主题增加流量添加路由器...在Shell中添加临时环境变量在.env添加开发环境变量我可以使用装饰器吗...
它提供了许多装饰器和指南来编写您的代码。 这是什么 Ts.ED 是基于 Express/Koa.js 的 Node.js 和 TypeScript 框架。 Ts.ED 是一个基于 Express/Koa 的框架,用于使用 TypeScript(或 ES6)编写您的应用程序。 它...
我可以使用装饰器吗? 使用AJAX请求获取数据 与API后端集成 节点 Ruby on Rails 在开发中代理API请求 配置代理后出现“无效的主机头”错误 手动配置代理 配置WebSocket代理 在开发中使用HTTPS 在服务器上生成动态...
大家都说名字太长不太容易被人记住:对正则表达式,IO,装饰器,面向对象,常用内置模块都有一个比较全面的解释,如果已经熟练掌握学习手册的内容,这本书可以作为工具书,解决一些常见的实际问题,如果之前熟悉java...
函数内建函数和可迭代对象,迭代器函数匿名函数生成器函数和yield from语法高阶函数与函数的柯里化递归类型注解与参数注解装饰器functools模块5.文件IO操作文件操作StringIO和BytesIO路径操作高级文件操作模块shutil...
Project为现代工具(如 , 实现了装饰器 安装 npm install @decorators/di --save npm install @decorators/express --save npm install @decorators/socket --save 使用例 这是Express框架用法的示例。 它使用...