I understand the composite design pattern and the decorator design pattern and their uses. Can we have a case where we have to use them together? How would the class diagram for such a scenario look like?
Will we have the decorator(from Decorator design pattern), leaf nodes, and composite(from Composite design pattern) inherited from the Component? Here is what I am referring to for the decorator pattern:wiki link for decorator pattern and for composite pattern: composite wiki link
The decorator decorates a single object at the same time delegating its methods and hence modifying its behavior. Consider an interface Text
with a single method String asString();
an example classes such as TrimmedText
, UpperCaseText
, and LowerCaseText
.
The composite is a container of zero to n
objects and just delegates behavior to its children.
These, however, can be combined into something called a composite decorator, which would be ConcatenatedText
with respect to the previous examples.
Here is some code that proves the composite class can also act as a decorator and be decorated itself:
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")
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With