我创建装饰器模式示例:
界面:
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
我听不懂以下内容:
如何创建装饰器?对我而言-装饰器implements
与原始类或示例中的接口相同-装饰器是extends
来自另一个装饰器,等等。link for extends realization
在BufferedInputStream的示例中可能是这样的实现,只是因为抽象类是在开始而不是在接口上选择的?
编辑:
换句话说,我不明白CarDecorator
的用途是什么
LuxerCar
和SportsCar
可以与implement Car
的{{1}}接口和not extends
进行交互。有什么好处?
答案 0 :(得分:7)
BufferedInputStream
的实现方式与您的Car
示例完全相同。它装饰了InputStream
,尽管它是一个抽象类,但它仍然提供了契约,就像接口一样。在这种情况下,我们选择了一个抽象类,因为有些方法具有默认行为(read
和skip
),并且在编写该类时,接口无法支持该方法(现在,它们可以,但是default methods
在界面中添加的时间要晚得多。
因为合同使用了抽象类,所以BufferedInputStream
扩展了FilterInputStream
,就像CarDecorator
实现了Car
一样。两者都是代表的简单持有者。它们包含单个protected
字段(InputStream
和Car
),并将所有方法调用委托给该字段。这样做的原因是,如果合同中包含大量方法,则委派每个装饰器中的所有方法可能会导致大量代码重复。当您的界面只有一个方法(如您的方法)时,那么它带来的好处就很小。
这当然不是装饰器模式的必要组件;这只是实现它的方式略有不同。您的实现仍然是装饰器模式的100%正确实现。