You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Taking our sentence example from above. Here we have the base class `LetterComposite` and the
37
-
different printable types `Letter`, `Word` and `Sentence`.
43
+
Taking our sentence example from above. Here we have the base class `LetterComposite` and the
44
+
different printable types `Letter`, `Word` and `Sentence`.
38
45
39
46
```java
40
47
publicabstractclassLetterComposite {
41
48
42
-
privatefinalList<LetterComposite> children =newArrayList<>();
49
+
privatefinalList<LetterComposite> children =newArrayList<>();
43
50
44
-
publicvoidadd(LetterCompositeletter) {
45
-
children.add(letter);
46
-
}
51
+
publicvoidadd(LetterCompositeletter) {
52
+
children.add(letter);
53
+
}
47
54
48
-
publicintcount() {
49
-
return children.size();
50
-
}
55
+
publicintcount() {
56
+
return children.size();
57
+
}
51
58
52
-
protectedvoidprintThisBefore() {
53
-
}
59
+
protectedvoidprintThisBefore() {
60
+
}
54
61
55
-
protectedvoidprintThisAfter() {
56
-
}
62
+
protectedvoidprintThisAfter() {
63
+
}
57
64
58
-
publicvoidprint() {
59
-
printThisBefore();
60
-
children.forEach(LetterComposite::print);
61
-
printThisAfter();
62
-
}
65
+
publicvoidprint() {
66
+
printThisBefore();
67
+
children.forEach(LetterComposite::print);
68
+
printThisAfter();
69
+
}
63
70
}
64
71
65
72
publicclassLetterextendsLetterComposite {
66
73
67
-
privatefinalchar character;
74
+
privatefinalchar character;
68
75
69
-
publicLetter(charc) {
70
-
this.character = c;
71
-
}
76
+
publicLetter(charc) {
77
+
this.character = c;
78
+
}
72
79
73
-
@Override
74
-
protectedvoidprintThisBefore() {
75
-
System.out.print(character);
76
-
}
80
+
@Override
81
+
protectedvoidprintThisBefore() {
82
+
System.out.print(character);
83
+
}
77
84
}
78
85
79
86
publicclassWordextendsLetterComposite {
80
87
81
-
publicWord(List<Letter>letters) {
82
-
letters.forEach(this::add);
83
-
}
88
+
publicWord(List<Letter>letters) {
89
+
letters.forEach(this::add);
90
+
}
84
91
85
-
publicWord(char... letters) {
86
-
for (char letter : letters) {
87
-
this.add(newLetter(letter));
92
+
publicWord(char... letters) {
93
+
for (char letter : letters) {
94
+
this.add(newLetter(letter));
95
+
}
88
96
}
89
-
}
90
97
91
-
@Override
92
-
protectedvoidprintThisBefore() {
93
-
System.out.print("");
94
-
}
98
+
@Override
99
+
protectedvoidprintThisBefore() {
100
+
System.out.print("");
101
+
}
95
102
}
96
103
97
104
publicclassSentenceextendsLetterComposite {
98
105
99
-
publicSentence(List<Word>words) {
100
-
words.forEach(this::add);
101
-
}
106
+
publicSentence(List<Word>words) {
107
+
words.forEach(this::add);
108
+
}
102
109
103
-
@Override
104
-
protectedvoidprintThisAfter() {
105
-
System.out.print(".");
106
-
}
110
+
@Override
111
+
protectedvoidprintThisAfter() {
112
+
System.out.print(".");
113
+
}
107
114
}
108
115
```
109
116
@@ -112,52 +119,52 @@ Then we have a messenger to carry messages:
112
119
```java
113
120
publicclassMessenger {
114
121
115
-
LetterCompositemessageFromOrcs() {
122
+
LetterCompositemessageFromOrcs() {
116
123
117
-
var words =List.of(
118
-
newWord('W', 'h', 'e', 'r', 'e'),
119
-
newWord('t', 'h', 'e', 'r', 'e'),
120
-
newWord('i', 's'),
121
-
newWord('a'),
122
-
newWord('w', 'h', 'i', 'p'),
123
-
newWord('t', 'h', 'e', 'r', 'e'),
124
-
newWord('i', 's'),
125
-
newWord('a'),
126
-
newWord('w', 'a', 'y')
127
-
);
124
+
var words =List.of(
125
+
newWord('W', 'h', 'e', 'r', 'e'),
126
+
newWord('t', 'h', 'e', 'r', 'e'),
127
+
newWord('i', 's'),
128
+
newWord('a'),
129
+
newWord('w', 'h', 'i', 'p'),
130
+
newWord('t', 'h', 'e', 'r', 'e'),
131
+
newWord('i', 's'),
132
+
newWord('a'),
133
+
newWord('w', 'a', 'y')
134
+
);
128
135
129
-
returnnewSentence(words);
136
+
returnnewSentence(words);
130
137
131
-
}
138
+
}
132
139
133
-
LetterCompositemessageFromElves() {
140
+
LetterCompositemessageFromElves() {
134
141
135
-
var words =List.of(
136
-
newWord('M', 'u', 'c', 'h'),
137
-
newWord('w', 'i', 'n', 'd'),
138
-
newWord('p', 'o', 'u', 'r', 's'),
139
-
newWord('f', 'r', 'o', 'm'),
140
-
newWord('y', 'o', 'u', 'r'),
141
-
newWord('m', 'o', 'u', 't', 'h')
142
-
);
142
+
var words =List.of(
143
+
newWord('M', 'u', 'c', 'h'),
144
+
newWord('w', 'i', 'n', 'd'),
145
+
newWord('p', 'o', 'u', 'r', 's'),
146
+
newWord('f', 'r', 'o', 'm'),
147
+
newWord('y', 'o', 'u', 'r'),
148
+
newWord('m', 'o', 'u', 't', 'h')
149
+
);
143
150
144
-
returnnewSentence(words);
151
+
returnnewSentence(words);
145
152
146
-
}
153
+
}
147
154
148
155
}
149
156
```
150
157
151
158
And then it can be used as:
152
159
153
160
```java
154
-
var messenger=newMessenger();
161
+
var messenger=newMessenger();
155
162
156
-
LOGGER.info("Message from the orcs: ");
157
-
messenger.messageFromOrcs().print();
163
+
LOGGER.info("Message from the orcs: ");
164
+
messenger.messageFromOrcs().print();
158
165
159
-
LOGGER.info("Message from the elves: ");
160
-
messenger.messageFromElves().print();
166
+
LOGGER.info("Message from the elves: ");
167
+
messenger.messageFromElves().print();
161
168
```
162
169
163
170
The console output:
@@ -178,16 +185,44 @@ Message from the elves:
178
185
Use the Composite pattern when
179
186
180
187
* You want to represent part-whole hierarchies of objects.
181
-
* You want clients to be able to ignore the difference between compositions of objects and
182
-
individual objects. Clients will treat all objects in the composite structure uniformly.
188
+
* You want clients to be able to ignore the difference between compositions of objects and
189
+
individual objects. Clients will treat all objects in the composite structure uniformly.
183
190
184
191
## Known uses
185
192
186
-
*[java.awt.Container](http://docs.oracle.com/javase/8/docs/api/java/awt/Container.html) and [java.awt.Component](http://docs.oracle.com/javase/8/docs/api/java/awt/Component.html)
187
-
*[Apache Wicket](https://github.com/apache/wicket) component tree, see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java) and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)
193
+
* Graphical user interfaces where components can contain other components (e.g., panels containing buttons, labels,
194
+
other panels).
195
+
* File system representations where directories can contain files and other directories.
196
+
* Organizational structures where a department can contain sub-departments and employees.
see [Component](https://github.com/apache/wicket/blob/91e154702ab1ff3481ef6cbb04c6044814b7e130/wicket-core/src/main/java/org/apache/wicket/Component.java)
201
+
and [MarkupContainer](https://github.com/apache/wicket/blob/b60ec64d0b50a611a9549809c9ab216f0ffa3ae3/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java)
202
+
203
+
## Consequences
204
+
205
+
Benefits:
206
+
207
+
* Simplifies client code, as it can treat composite structures and individual objects uniformly.
208
+
* Makes it easier to add new kinds of components, as existing code doesn't need to be changed.
209
+
210
+
Trade-offs:
211
+
212
+
* Can make the design overly general. It might be difficult to restrict the components of a composite.
213
+
* Can make it harder to restrict the types of components in a composite.
214
+
215
+
## Related Patterns
216
+
217
+
*[Flyweight](https://java-design-patterns.com/patterns/flyweight/): Composite can use Flyweight to share component
218
+
instances among several composites.
219
+
*[Iterator](https://java-design-patterns.com/patterns/iterator/): Can be used to traverse Composite structures.
220
+
*[Visitor](https://java-design-patterns.com/patterns/visitor/): Can apply an operation over a Composite structure.
188
221
189
222
## Credits
190
223
191
224
*[Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59)
192
225
*[Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b)
193
226
*[Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7)
227
+
*[Pattern-Oriented Software Architecture, Volume 1: A System of Patterns](https://amzn.to/3xoLAmi)
228
+
*[Patterns of Enterprise Application Architecture](https://amzn.to/3vBKXWb)
0 commit comments