具有复合设计模式的装饰器设计模式
Decorator design pattern with Composite Design pattern
我了解复合设计模式和装饰器设计模式及其用途。我们可以有一个我们必须一起使用它们的情况吗?这种情况下的 class 图会是什么样子?
我们是否会从组件继承装饰器(来自装饰器设计模式)、叶节点和复合材料(来自复合设计模式)?
这是我指的装饰器模式:wiki link for decorator pattern
对于复合模式:composite wiki link
装饰器在装饰单个对象的同时委托其方法并因此修改其行为。考虑具有单个方法 String asString();
的接口 Text
一个示例 class,例如 TrimmedText
、UpperCaseText
和 LowerCaseText
。
复合体是零到 n
个对象的容器,仅将行为委托给其子对象。
然而,这些可以组合成一个叫做 复合装饰器 的东西,相对于前面的示例,这将是 ConcatenatedText
。
下面是一些代码,证明复合 class 也可以充当装饰器并自己被装饰:
interface Text {
String asString();
// just a static helper to construct an instance of Text quickly
static Text of(String text) {
return () -> text;
}
}
// 1st decorator
@AllArgsConstructor
static class TrimmedText implements Text {
Text text;
@Override
public String asString() {
return text.asString().trim();
}
}
// 2nd decorator
@AllArgsConstructor
static class UpperCaseText implements Text {
Text text;
@Override
public String asString() {
return text.asString().toUpperCase();
}
}
// composite decorator
@AllArgsConstructor
static class ConcatenatedText implements Text {
List<Text> texts;
public void add(String text) {
texts.add(Text.of(text));
}
@Override
public String asString() {
return texts.stream().map(Text::asString).collect(Collectors.joining(", "));
}
}
@Test
void foo() {
Text trimmedUpperCaseText = new TrimmedText(new UpperCaseText(Text.of(" a b c ")));
assertThat(trimmedUpperCaseText.asString(), is("A B C"));
ConcatenatedText concatenatedText = new ConcatenatedText(new ArrayList<>(List.of(
new UpperCaseText(Text.of(" a ")),
new TrimmedText(Text.of(" b ")))));
concatenatedText.add("c");
Text refinedText = new TrimmedText(concatenatedText);
assertThat(refinedText.asString(), is("A , b, c")
}
是的,decorator pattern is often used together with a composite pattern. Here is what GoF 说:
Decorator is often used with Composite. When decorators and composites are used together, they will usually have a common parent class. So decorators will have to support the Component interface (...)
原因是复合模式的目标是让:
clients treat individual objects and compositions of objects uniformely.
将两者结合起来可以使用装饰器向复合材料和叶子添加功能和职责,因此使用 composition over inheritance。主要好处是:
- 避免不太灵活继承的缺点
- 避免重复实现通用接口的弊端
- 如果目标是添加共同职责,则允许对组合和叶子重用相同的装饰器
结果如下:
有趣的是,装饰器模式在图形上看起来与复合模式相似,这可能让人感到不安。 GoF解释了这种感觉:
A decorator can be viewed as a degenerate composite with only one component. However a decorator adds additional responsibilities (...)
我了解复合设计模式和装饰器设计模式及其用途。我们可以有一个我们必须一起使用它们的情况吗?这种情况下的 class 图会是什么样子?
我们是否会从组件继承装饰器(来自装饰器设计模式)、叶节点和复合材料(来自复合设计模式)? 这是我指的装饰器模式:wiki link for decorator pattern 对于复合模式:composite wiki link
装饰器在装饰单个对象的同时委托其方法并因此修改其行为。考虑具有单个方法 String asString();
的接口 Text
一个示例 class,例如 TrimmedText
、UpperCaseText
和 LowerCaseText
。
复合体是零到 n
个对象的容器,仅将行为委托给其子对象。
然而,这些可以组合成一个叫做 复合装饰器 的东西,相对于前面的示例,这将是 ConcatenatedText
。
下面是一些代码,证明复合 class 也可以充当装饰器并自己被装饰:
interface Text {
String asString();
// just a static helper to construct an instance of Text quickly
static Text of(String text) {
return () -> text;
}
}
// 1st decorator
@AllArgsConstructor
static class TrimmedText implements Text {
Text text;
@Override
public String asString() {
return text.asString().trim();
}
}
// 2nd decorator
@AllArgsConstructor
static class UpperCaseText implements Text {
Text text;
@Override
public String asString() {
return text.asString().toUpperCase();
}
}
// composite decorator
@AllArgsConstructor
static class ConcatenatedText implements Text {
List<Text> texts;
public void add(String text) {
texts.add(Text.of(text));
}
@Override
public String asString() {
return texts.stream().map(Text::asString).collect(Collectors.joining(", "));
}
}
@Test
void foo() {
Text trimmedUpperCaseText = new TrimmedText(new UpperCaseText(Text.of(" a b c ")));
assertThat(trimmedUpperCaseText.asString(), is("A B C"));
ConcatenatedText concatenatedText = new ConcatenatedText(new ArrayList<>(List.of(
new UpperCaseText(Text.of(" a ")),
new TrimmedText(Text.of(" b ")))));
concatenatedText.add("c");
Text refinedText = new TrimmedText(concatenatedText);
assertThat(refinedText.asString(), is("A , b, c")
}
是的,decorator pattern is often used together with a composite pattern. Here is what GoF 说:
Decorator is often used with Composite. When decorators and composites are used together, they will usually have a common parent class. So decorators will have to support the Component interface (...)
原因是复合模式的目标是让:
clients treat individual objects and compositions of objects uniformely.
将两者结合起来可以使用装饰器向复合材料和叶子添加功能和职责,因此使用 composition over inheritance。主要好处是:
- 避免不太灵活继承的缺点
- 避免重复实现通用接口的弊端
- 如果目标是添加共同职责,则允许对组合和叶子重用相同的装饰器
结果如下:
有趣的是,装饰器模式在图形上看起来与复合模式相似,这可能让人感到不安。 GoF解释了这种感觉:
A decorator can be viewed as a degenerate composite with only one component. However a decorator adds additional responsibilities (...)