用于IO的GoF Decorator模式的用例和示例

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用于IO的GoF Decorator模式的用例和示例相关的知识,希望对你有一定的参考价值。

我在wikipedia中读到,Decorator模式用于.Net和Java IO类。

任何人都能解释一下这是如何使用的吗?它有一个可能的例子,有什么好处?

维基百科上有一个Windows窗体的例子,但我想知道Java IO类是如何发生的。

答案

InputStream是一个抽象类。像BufferedInputStreamGzipInputStreamObjectInputStream等大多数具体实现都有一个构造函数,它接受相同抽象类的实例。这是装饰器模式的识别键(这也适用于采用相同接口实例的构造函数)。

当使用这样的构造函数时,所有方法都将委托给包装的实例,并改变方法的行为方式。例如,事先在内存中缓冲流,预先解压缩流或以不同方式解释流。有些甚至还有其他方法最终也会进一步委托给包装的实例。这些方法用额外的行为装饰包装的实例。

假设我们在Gzip文件中有一堆序列化的Java对象,我们希望快速读取它们。

首先打开它的输入流:

FileInputStream fis = new FileInputStream("/objects.gz");

我们想要速度,所以让它在内存中缓冲:

BufferedInputStream bis = new BufferedInputStream(fis);

该文件是gzip压缩的,所以我们需要解压缩它:

GzipInputStream gis = new GzipInputStream(bis);

我们需要反序列化这些Java对象:

ObjectInputStream ois = new ObjectInputStream(gis);

现在我们终于可以使用它了:

SomeObject someObject = (SomeObject) ois.readObject();
// ...

好处是您可以使用一个或多个装饰器来自由地装饰流以满足您的需求。这比为ObjectGzipBufferedFileInputStreamObjectBufferedFileInputStreamGzipBufferedFileInputStreamObjectGzipFileInputStreamObjectFileInputStreamGzipFileInputStreamBufferedFileInputStream等每种可能的组合提供单一课程要好得多。

请注意,当您即将关闭流时,只需关闭最外面的装饰器即可。它会将关闭呼叫一直委托给底部。

ois.close();

See also:

另一答案

让我们在浏览java IO类之前了解Decorator模式的组件。

enter image description here

Decorator模式有四个组成部分

  1. 组件:组件定义可以动态添加任务的对象的接口
  2. ConcreteComponent:它只是Component接口的一个实现
  3. Decorator:Decorator具有对Component的引用,并且还符合Component接口。装饰器本质上是包装组件
  4. ConcreteDecorator:ConcreteDecorator只是将责任添加到原始Component。

只要在设计时完成一些基础工作,装饰器模式可用于静态地(或在某些情况下)在运行时扩展(装饰)某个对象的功能,而与同一类的其他实例无关。这是通过设计一个包装原始类的新Decorator类来实现的。

现在让我们将这些概念映射到java.io pacakge类。

零件:

InputStream

此抽象类是表示输入字节流的所有类的超类。

需要定义InputStream子类的应用程序必须始终提供返回输入的下一个字节的方法。

public abstract int read()是一种抽象方法。

ConcreteComponent:

FileInputStream

FileInputStream从文件系统中的文件获取输入字节。可用的文件取决于主机环境。

FileInputStream用于读取原始字节流,例如图像数据。要读取字符流,请考虑使用FileReader。

InputStream的所有ConcreteComponents的示例:

AudioInputStream, ByteArrayInputStream, FileInputStream, FilterInputStream, 
InputStream, ObjectInputStream, PipedInputStream, SequenceInputStream, 
StringBufferInputStream

装饰:

FilterInputStream

FilterInputStream包含一些其他输入流,它将其用作其基本数据源,可能会沿途转换数据或提供其他功能。

请注意FilterInputStream实现InputStream => Decorator实现Component,如UML图所示。

public class FilterInputStream
extends InputStream

ConcreteDecorator:

BufferedInputStream

BufferedInputStream将功能添加到另一个输入流 - 即缓冲输入并支持标记和重置方法的功能。

所有ConcreteDecorators的示例:

BufferedInputStream, CheckedInputStream, CipherInputStream, DataInputStream, 
DeflaterInputStream, DigestInputStream, InflaterInputStream, 
LineNumberInputStream, ProgressMonitorInputStream, PushbackInputStream

工作示例代码:

我用BufferedInputStream读取一个单词的每个字符,它已存储在一个文本文件a.txt中

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("a.txt")));
while(bis.available()>0)
{
        char c = (char)bis.read();
        System.out.println("Char: "+c);;
}

何时使用此模式:

  1. 应动态添加/删除对象职责和行为
  2. 具体实施应与责任和行为分离
  3. 当子类化成本太高而无法动态添加/删除职责时
另一答案

在.NET中,有许多流装饰器,如BufferedStream,CryptoStream,GzipStream等。所有这些都装饰了Stream类。

另一答案

当您操作输入/输出流时,装饰器模式在java.io类中使用(同样适用于读者和编写者)。

inputstream,bytearrayinputstream,stringbuilderinputstreams等基于元素。 Filterinputstream是装饰器类的基类。过滤输入流(例如缓冲输入流)在读取流或写入流时可以执行其他操作。

它们是通过封装流来构建的,并且是流本身。

new BufferedReader( new FileInputStream() ).readLine();

我想不出在java.net中实现这种模式的任何类,但我认为你被告知这个包,因为它与java.io(例如socket.getInputStream)紧密相连。

实际上,here is a course from O'Relly解释了如何在java.io中实现装饰器。

此致,Stéphane

另一答案

A - Decorator Pattern

A.1 - Use Case of Decorator Pattern

装饰器模式用于在不更改遗留类的情况下扩展遗留功能。比方说,我们有一个实现接口的具体类。我们需要扩展现有方法的功能,因为现有的类及其方法已经被其他类使用,因此我们不希望在现有类中进行更改。但是我们还需要在新类上扩展功能,那么我们如何解决这个问题呢?

1- We can't change the existing legacy code
2- We want to extend the functionality

所以我们使用装饰器模式,将装饰器中的现有类包装起来。

B - 基本GoF装饰器模式示例

这里我们有一个简单的接口和一个实现/具体类。界面有一个简单的方法,即getMessageOfTheDay,它返回一个String。假设有很多其他类使用此方法。因此,如果我们想要在实现/具体类中进行更改,它将影响旧的遗留代码。我们只想为新类更改它,因此我们使用装饰器模式。

这是Gang Of Four装饰设计模式的一个简单例子;

B.1 - Greeter.java

public interface Greeter {
    String getMessageOfTheDay();
}

B.2 - BasicGreeter.java

public class BasicGreeter implements Greeter {

    @Override
    public String getMessageOfTheDay() {
        return "Welcome to my server";
    }

}

B.3 - Abstract Decorator Class: GreeterDecorator.java

public abstract class GreeterDecorator implements Greeter {

    protected Greeter greeter;

    public GreeterDecorator(Greeter greeter) {
        this.greeter = greeter;
    }

    public String getMessageOfTheDay() {
        return greeter.getMessageOfTheDay();
    }

}

B.4 - Concrete Decorator Class: StrangerDecorator.java

public class StrangerDecorator extends GreeterDecorator {

    public StrangerDecorator(Greeter greeter) {
        super(greeter);
    }

    @Override
    public String getMessageOfTheDay() {
        return "Hello Stranger " + super.getMessageOfTheDay();
    }

}

B.5 - Demo Code: DecoratorDemo .java

public class DecoratorDemo {

    public static void main(String[] args) {
        Greeter greeter = new BasicGreeter();

        String motd = greeter.get

以上是关于用于IO的GoF Decorator模式的用例和示例的主要内容,如果未能解决你的问题,请参考以下文章

GOF 23设计模式之(结构型模式二)

设计模式-Composite(结构型模式) 用于 递归构建 树 状 的组合结构,与Decorator的区别是 Composite旨在通过构造子类而添加新操作,而Decorator直接添加新操作。(代

使用Rational Rose进行用例图和活动图(转)

使用Rational Rose进行用例图和活动图(转)

Java,设计模式:用例和参与者管理器

MySql JSON 数据类型的用例