繁体   English   中英

装饰设计模式违背是一种关系

[英]decorator design pattern violating is-a relationship

我最近开始研究装饰设计模式,但我有一个查询。 装饰器实现与他们试图装饰的组件相同的接口。 这不违反is-a关系。 此外,由于装饰器具有组件(通过组合),为什么装饰器实际上需要实现混凝土组件实现的相同组件接口。

通过Headfirst上的装饰器设计模式,它让我觉得装饰者可以直接实现组件。 没有必要为装饰器提供抽象类/接口。

我担心这可能是一个愚蠢的问题,但帮助将使我有一个坚实的基础。

理解构图和装饰者之间的区别非常重要。 装饰器是一种组合形式,但是将它区分开来的主要原因在于它以允许包装器使用通常使用装饰对象的代码的方式实现。

让我们用一个常见的例子来帮助探索这个问题。 考虑接口InputStream 我可能有一个方法将字节从一个流复制到另一个流:

public static void copy(InputStream in, OutputStream out) { ... }

现在说我们有一个我们想复制的文件。 我将创建一个FileInputStream并将其传递给copy()

但是我说我需要计算复制的字节数。

好吧,我可以创建CountingFileInputStream ,它扩展了FileInputStream CountingFileInputStream是一个FileInputStream 但是如果明天我需要为SocketInputStream做同样的事情呢? 我必须创建一个扩展SocketInputStreamCountingSocketInputStream

我可以改用构图! 我可以创建一个接受InputStream的类并计算读取它的字节:

public class StreamCounter {

   private final InputStream in;
   private long bytesRead;

   public int read() {
     int nextByte = in.read();
     if (nextByte != -1) bytesRead++;
     return nextByte;
   }
}

这可以处理任何 InputStream ,这很棒。 但是我们不能使用我们现有的带有InputStream代码,因为StreamCounter 不是一个 InputStream

所以这就是Decorator的用武之地。我们可以改为创建一个CountingInputStream ,它既实现了InputStream ,又实现了一个 InputStream并委托给另一个InputStream 这样我们就可以在copy()方法中使用它。

简而言之,就is-a关系而言, CountingInputStream是一个InputStream (通常我们都在关注),但它不是一个FileInputStream ,它允许它包装任何InputStream ,就像装饰的LimitInputStream一样一个DeflaterInputStream ,用于装饰正在装饰FileInputStreamBufferedInputStream 并且在一天结束时, copy()不需要关心!

您可以根据用例选择如何实现Decorator类。 Decorator类不必强制实现相同的接口。

因此,如果您看到Collections.synchronizedCollection.(Collection<T> c) ,我们在这里有一个静态方法,它充当装饰器,并且没有实现相同的接口。

但是在实现中,这个链接 Decorator类确实实现了接口,因为用例需要它[因为使用了多态]。

所以它不是强制性的,也没有“是一种”关系的消息。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM