装饰器模式实现 - 扩展vs实现

ip6*_*696 4 java design-patterns decorator

我创建装饰模式示例:

接口:

public interface Printer {
  void print(String message);
}
Run Code Online (Sandbox Code Playgroud)

执行:

public class StringPrinter implements Printer {

  public void print(String message) {
    System.out.println(message);
  }
}
Run Code Online (Sandbox Code Playgroud)

和2个装饰者:

将字符串更改为大写:

public class UpCasePrinter implements Printer {

  private Printer printer;

  public UpCasePrinter(Printer printer) {
    this.printer = printer;
  }

  public void print(String message) {
    printer.print(message.toUpperCase());
  }
}
Run Code Online (Sandbox Code Playgroud)

打印反向字符串:

public class InversePrinter implements Printer {

  private Printer printer;

  public InversePrinter(Printer printer) {
    this.printer = printer;
  }

  public void print(String message) {
    StringBuilder builder = new StringBuilder(message);
    printer.print(builder.reverse().toString());
  }
}
Run Code Online (Sandbox Code Playgroud)

一切正常.但在阅读不同网站上的示例时,我发现了不同的实现.extends来自另一个的每个decarator .我看到了实现BufferedInputStream

BufferedInputStream extends FilterInputStream
FilterInputStream extends InputStream
public abstract class InputStream implements Closeable
Run Code Online (Sandbox Code Playgroud)

我无法理解以下内容:

  1. 如何创建装饰器有区别吗?至于我 - 装饰器implements与原始类相同的接口或在示例中 - 装饰器extends来自另一个装饰器等链接用于扩展实现

  2. 可能在BufferedInputStream的示例中这样的实现只是因为在开始时选择了抽象类而不是接口?

编辑:

在此输入图像描述

换句话说,我不明白有什么用 CarDecorator

LuxerCar并且SportsCar可以implement Car接口和not extends来自CarDecorator.有什么好处?

Mic*_*ael 7

BufferedInputStream实现方式与您的Car示例完全相同.它装饰了一个InputStream,虽然它是一个抽象类,仍然提供契约,就像接口一样.在这种情况下选择了一个抽象类,因为有些方法具有默认行为(readskip),并且在编写类时,接口无法支持它(它们现在可以,但 接口中的默认方法稍后添加) .

因为抽象类用于合同,所以BufferedInputStream扩展FilterInputStream,就像CarDecorator实现一样Car.两者都只是代表的简单持有人.它们包含单个protected字段(an InputStream和a Car),并委托对该字段的所有方法调用.这样做的原因是,如果您的合同中有大量方法,则委托每个装饰器中的所有方法可能会导致大量代码重复.当你的界面只有一个方法时,就像你的那样,那么它提供的好处很少.

这当然不是装饰器模式的必要组成部分; 它只是一种稍微不同的实现方式.您的实现仍然是装饰器模式的100%正确实现.