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

时间:2018-07-16 10:21:27

标签: java design-patterns decorator

我创建装饰器模式示例:

界面:

public interface Printer {
  void print(String message);
}

实现:

public class StringPrinter implements Printer {

  public void print(String message) {
    System.out.println(message);
  }
}

和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());
  }
}

打印反向字符串:

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());
  }
}

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

的实现
BufferedInputStream extends FilterInputStream
FilterInputStream extends InputStream
public abstract class InputStream implements Closeable

我听不懂以下内容:

  1. 如何创建装饰器?对我而言-装饰器implements与原始类或示例中的接口相同-装饰器是extends来自另一个装饰器,等等。link for extends realization

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

编辑:

enter image description here

换句话说,我不明白CarDecorator的用途是什么

LuxerCarSportsCar可以与implement Car的{​​{1}}接口和not extends进行交互。有什么好处?

1 个答案:

答案 0 :(得分:7)

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

因为合同使用了抽象类,所以BufferedInputStream扩展了FilterInputStream,就像CarDecorator实现了Car一样。两者都是代表的简单持有者。它们包含单个protected字段(InputStreamCar),并将所有方法调用委托给该字段。这样做的原因是,如果合同中包含大量方法,则委派每个装饰器中的所有方法可能会导致大量代码重复。当您的界面只有一个方法(如您的方法)时,那么它带来的好处就很小。

这当然不是装饰器模式的必要组件;这只是实现它的方式略有不同。您的实现仍然是装饰器模式的100%正确实现。