1. 装饰者模式的详解
装饰者模式动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性
的替代方案。
装饰者模式设计类之间的关系:
其中Component是一个超类,ConcreteComponen是被装饰者,Decorator是装饰者,装饰者和被装饰者有共同的超类Component,但是此时我们发现Decorator和Component还有另外一条线,这条线表示Decorator还要组合Component。
在我看来装饰的模式中这几个类的主要作用如下:
首先我们看一个这样的现象(这个是我在网上看到的例子,我把它引入进来主要是方便谈谈我的理解)
现象描述:
如果说继承里的超类是一个模具(Component),做出各种各样的稍有不同的子类成品(ConcreteComponen,ConcreteDecoratorA,ConcreteDecoratorB)来满足各种各样的功能。那么把装饰模式比作的一条生产线吧,一个产品(ConcreteComponen)传过来,在各道工序不断地给它加上新的功能,把它一步步按照顺序包装成一个全新的产品(Concrete DecoratorA,Concrete DecoratorB)。记住,这条生产线可能是无限长的,这种包装也可以是无限添加的。
我的理解
1. Component是超类,他出现的意义是什么呢?照理说Decorator直接去组合ConcreteComponent,就可以去加强ConcreteComponent的行为,成而加工出一个不通的子类成品。但是可能有这样一种情况,ConcreteComponent的平级的区域内还有ConcreteComponent1,ConcreteComponent2……这样要为每一个ConcreteComponent都去写一个Decorator吗?这样显然不可能。所以抽象出Component的一个好处就是让ConcreteComponent和Decorator彼此解耦。Decorator只要得到Component对象的引用即可。
2. Decorator是装饰者,而真正装饰的过程是在Decorator的子类ConcreteDecoratorA和ConcreteDecoratorB中完成的,他们使用不同的装饰方法,作出了不同的子类成品。Decorator的作用只是告诉大家,我要去装饰ConcreteComponent,或许还会提供一些用这个装饰者去装饰的而形成的成品共用的特性和功能。
3. 装饰者永远是装饰者,但装饰者装饰出来的成品也有可能会变成被装饰者。即ConcreteDecoratorA和ConcreteDecoratorB有一天也会变到ConcreteComponen的地位。
只不过这个时候在ConcreteDecoratorA的旁边可能会出现一个类似于Decorator的装饰者DecoratorA,它同样要继承并组合超类Component。目的是相同的:解耦,让一个装饰者不必为一个被装饰者而存在
这时候的装饰者模式的结构图变成:
由上图说明一个道理,如果条件容许的话Decorator和DecoratorA的位置是可以互相交换的。这就像冲一杯带糖的奶粉,Decorator表示放糖,DecoratorA表示放奶粉,其实是先放糖还是先放奶粉,最终都能得到ConcreteDecoratorAA(一杯带糖的奶粉)。当然这是在条件容许的情况下,在有些生产环境中,制做工序(装饰的先后)是不能乱的。
2. 装饰者模式在JAVA IO中的应用
先给出Java IO包中主要类的关系:
java IO包中有四大等级结构InputStream,outputStream, InputStreamReader,outputStreamReader。InputStream和OutputStream处理8位字节流数据, Reader和Writer处理16位的字符流数据。InputStream和Reader处理输入, OutputStream和Writer处理输出。各个体系内部用到的都是装饰者模式,而InputStream和InputStreamReader之间,outputStream和outputStreamReader之间用的是适配器模式
下面主要以InputStream和InputStreamReader为例详解
1. 从装饰者模式看InputStream结构
InputStream的类图关系
class java.lang.Object
|
|—class java.io.InputStream //输入流,字节形式,为以下的基类
| |
| |——ByteArrayInputStream //从字节数组中读取
| |
| |——FileInputStream //从文件中读取数据
| |
| |—— FilterInputStream //过滤流的基类,
| | | // 过滤可以了解为各种处理技术的形象称呼
| | |
| | |——BufferedInputStream //缓冲技术,
| | | // 数据来自底层输入流
| | |
| | |——DataInputStream //可读java数据类型
| | |
| | |——PushbackInputStream //缓冲技术,
| | | // 数据来自任意输入流
| | |
| | |——java.util.zip.GZIPInputStream
| | | //不是java.io包中的流。压缩技术
| | |
| | |——java.security.DigestInputStream
| | | //不是java.io包中的流。处理流的摘要
| | |
| |—— .......
从图中可以看出,InputStream就是装饰者模式中的超类(Component),ByteArrayInputStream,FileInputStream相当于被装饰者(ConcreteComponent),这些类都提供了最基本的字节读取功能。
而另外一个和这两个类是同一级的类FilterInputStream即是装饰者(Decorator),BufferedInputStream,DataInputStream,PushbackInputStream…这些都是被装饰者装饰后形成的成品。
根据装饰者模式的特点,我们可以总结出这些IO流的使用方法:
File file = new File ("hello.txt");
FileInputStream in=new FileInputStream(file);
BufferedInputStream inBuffered=new BufferedInputStream (in);
这里BufferedInputStream主要是提供了缓存机制,先读入一个byte[],等count到达缓存Byte[]的大小的时候,再一次读入。
当然你也可以写成BufferedInputStream inBuffered =
new BufferedInputStream (new FileInputStream(new File ("hello.txt")));
从使用的角度来看装饰者模式,可以看出它的一个缺点:装饰者模式的实现对于使用者是透明的,当使用者不熟悉你的实现的时,就很难理解。
同理你可以学习一下另外一个结构outputStream
2. 适配器模式看InputStreamReader
适配器模式比较简单就不多讲了,主要是解决了java无法多继承的问题,下面大概讲一下IO包中是怎么用这个模式的,用它来做什么?
InputStreamReader和InputStream的功能的不同点在于InputStream是以二进制输入 / 输出, I/O 速度快且效率高,由于读到的是字节,也就不存在乱码问题,平台移植性好。但是它的 read ()方法读到的是一个字节,很不利于人们阅读。InputStreamReader类将字节转换为字符。 你可以在构造器中指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式。
Java.io.Reader类提供了要求了继承这个类的所有类必须提供
/**
* Reads characters into a portion of an array. This method will block
* until some input is available, an I/O error occurs, or the end of the
* stream is reached.
*
* @param cbuf Destination buffer
* @param off Offset at which to start storing characters
* @param len Maximum number of characters to read
*
* @return The number of characters read, or -1 if the end of the
* stream has been reached
*
* @exception IOException If an I/O error occurs
*/
abstract public int read(char cbuf[], int off, int len) throws IOException;
代码注释理解:读出来的形式必须是字符,而不是字节了,InputStreamReader继承于Reader,即具备了读出字符的功能,而把什么读成字节的功能就要InputStreamReader去适配了,InputStreamReader的构造函数是这样的:
/**
* Creates an InputStreamReader that uses the named charset.
*
* @param in
* An InputStream
*
* @param charsetName
* The name of a supported
* {@link java.nio.charset.Charset </code>charset<code>}
*
* @exception UnsupportedEncodingException
* If the named charset is not supported
*/
public InputStreamReader(InputStream in, String charsetName)
throws UnsupportedEncodingException
{
super(in);
if (charsetName == null)
throw new NullPointerException("charsetName");
sd = StreamDecoder.forInputStreamReader(in, this, charsetName);
}
用的是InputStream去适配InputReader。
3. 浅谈Reader体系
Reader体系中同样用到的是装饰者模式,但是有一点不同,Reader体系中的FilterRead类和InputStream体系中的FilterInputStream的功能不同,它不再是装饰者。
这一点可以从BufferReader和BufferStreamReader的实现不同可以看出
bufferReader:public class BufferedReader extends Reader
BufferedInputStream:public class BufferedInputStream extends FilterInputStream
但模式还是相同的。在Reader我没找到FilterInputStream类似作用的东西
下面看看Reader IO的使用方法
1. File file = new File ("hello.txt");
2. FileInputStream in=new FileInputStream(file);
3. InputStreamReader inReader=new InputStreamReader(in);
4. BufferedReader bufReader=new BufferedReader(inReader);
可以看出步骤2到3使用的是适配器模式,而3到4使用的是装饰者模式
好了,以上就是我学习设计模式和java IO的心得,自己也是初学者,希望对同样这块不太了解的人有所帮助,有什么意见大家可以提出。
分享到:
相关推荐
总的来说,Java IO利用装饰模式构建了一个灵活且易于扩展的流处理框架,允许我们在运行时动态地增加流的功能,而无需改变原有代码。这种设计模式在许多其他领域也有广泛应用,如网络编程、数据库访问等,体现了面向...
总的来说,Java IO包是一个强大的工具集,通过Decorator模式实现了灵活的流处理。理解这个模式对于深入掌握Java IO非常重要,它不仅帮助我们更好地理解和使用Java提供的IO类,还可以启发我们在其他领域中应用类似的...
### Java JDK IO包类详解 #### 概述 Java平台提供的`io`包为开发者提供了访问文件系统、对象序列化等功能...总之,`java.io`包是Java编程语言的重要组成部分,对于任何想要深入理解Java平台的开发者来说都至关重要。
本文旨在为新手提供一个全面的Java I/O教程,帮助读者理解Java I/O的基本概念、架构以及如何使用这些API。 #### 二、Java I/O概述 Java中的I/O系统设计得非常灵活且强大,它将所有类型的输入/输出抽象成“流”的...
Java的IO库是一个复杂而强大的系统,其设计思想和实现方式体现了多种设计模式,包括Decorator(装饰者)模式和Adapter(适配器)模式。本文将深入探讨这两个模式在Java/IO中的应用,并通过实例解释它们如何使得Java...
### Java IO系统全面解析 #### 一、Java IO系统概述 Java IO系统是Java平台标准库中的一个重要组成部分,主要用于处理输入输出操作。...理解和掌握Java IO系统对于任何Java开发者来说都是非常重要的。
Java IO类库遵循一种称为“装饰者模式”的设计模式,这种模式允许开发者通过增加额外的行为来扩展现有的类,而不改变其结构。Java IO的类结构主要由以下几个层次构成: 1. **根接口**:`InputStream` 和 `...
Java IO完全总结的知识点: 一、历史背景: ...文章通过介绍Java IO的历史背景、分类、设计模式和特点,以及通过示例和源代码分析的方式,帮助读者深入理解Java IO系统,从而能够更加熟练地运用Java IO进行编程。
### Java IO详解 #### 1. 什么是IO 在计算机科学中,IO(Input/...理解Java IO的基本原理和类结构对于开发高效稳定的Java应用程序至关重要。通过合理选择和组合不同的流类,开发者可以轻松实现各种复杂的IO功能。
在实际应用中,装饰者模式常常用于对IO流的处理,如BufferedInputStream和DataOutputStream等,它们都继承自InputStream和OutputStream,通过组合的方式增加了缓冲和数据转换等功能。此外,还可以应用于UI组件的扩展...
Java的I/O设计遵循了一种称为“装饰者模式”的组织模式,允许在不改变原有类的基础上增加新的功能。 在进行I/O操作时,一般需要以下步骤: 1. 创建一个与特定介质(如文件、网络连接等)相关的输入/输出对象。 2. ...
总结来说,Java IO流是一个庞大的体系,覆盖了从基础的文件操作到复杂的网络通信,理解并熟练掌握这一部分将极大地提升Java开发者的技能。通过学习和实践,开发者可以灵活地处理各种数据输入输出场景,为应用程序...
Java IO是Java开发中不可或缺的一部分,涵盖了从文件读写到网络通信的各种场景。通过对这些基础知识的理解,开发者可以更好地构建稳定高效的应用程序。随着技术的发展,Java IO也在不断地演进和完善,例如NIO(New ...
在Java编程语言中,I/O(输入/输出)是处理数据传输的核心部分,尤其是在处理文件、网络通信或者系统间的数据交换时...此外,了解和使用装饰器模式也是理解Java IO流设计的关键,因为很多处理流就是装饰器模式的应用。
FilterInputStream和FilterOutputStream是过滤流,可以作为装饰者模式的实例,用于在原有流的基础上添加额外功能,如数据校验、压缩等。 以上内容涵盖了Java IO的基本知识点,通过理解和掌握这些概念,开发者可以...
Java IO 中广泛使用了装饰模式来增强基础流的功能,例如`BufferedInputStream`、`DataInputStream`等都是基于`InputStream`的装饰者。 #### 五、文件锁 Java IO 支持文件锁定机制,通过`FileLock`类可以防止多个...
- 处理流的使用可以增强输入输出操作的灵活性,例如,FilterInputStream和FilterOutputStream作为装饰者模式的实例,允许添加过滤、压缩等功能。 - 使用PrintStream和PrintWriter可以方便地进行格式化输出,包括...
Java的IO流体系是Java平台的核心...总之,Java的IO流体系通过其对称性质和装饰器模式,提供了灵活且强大的数据输入输出解决方案。理解这个体系结构,可以帮助开发者更好地利用Java进行文件操作、网络通信以及数据处理。