1
- using System ;
1
+ // EN: Composite Design Pattern
2
+ //
3
+ // Intent: Compose objects into tree structures to represent part-whole
4
+ // hierarchies. Composite lets clients treat individual objects and compositions
5
+ // of objects uniformly.
6
+ //
7
+ // RU: Паттерн Компоновщик
8
+ //
9
+ // Назначение: Объединяет объекты в древовидные структуры для представления
10
+ // иерархий часть-целое. Компоновщик позволяет клиентам обрабатывать отдельные
11
+ // объекты и группы объектов одинаковым образом.
12
+
13
+ using System ;
2
14
using System . Collections . Generic ;
3
15
4
16
namespace RefactoringGuru . DesignPatterns . Composite . Conceptual
5
17
{
18
+ // EN: The base Component class declares common operations for both simple and
19
+ // complex objects of a composition.
20
+ //
21
+ // RU: Базовый класс Компонент объявляет общие операции как для простых, так и
22
+ // для сложных объектов структуры.
6
23
abstract class Component
7
24
{
8
25
public Component ( ) { }
9
26
10
- public abstract void Operation ( ) ;
11
-
12
- public abstract void Add ( Component c ) ;
13
-
14
- public abstract void Remove ( Component c ) ;
15
-
16
- public abstract bool IsComposite ( ) ;
17
- }
18
-
19
- class Composite : Component
20
- {
21
- List < Component > children = new List < Component > ( ) ;
22
-
23
- public Composite ( )
24
- {
25
-
26
- }
27
-
28
- public override void Add ( Component component )
27
+ // EN: The base Component may implement some default behavior or leave it to
28
+ // concrete classes (by declaring the method containing the behavior as
29
+ // "abstract").
30
+ //
31
+ // RU: Базовый Компонент может сам реализовать некоторое поведение по
32
+ // умолчанию или поручить это конкретным классам, объявив метод, содержащий
33
+ // поведение абстрактным.
34
+ public abstract string Operation ( ) ;
35
+
36
+ // EN: In some cases, it would be beneficial to define the child-management
37
+ // operations right in the base Component class. This way, you won't need to
38
+ // expose any concrete component classes to the client code, even during the
39
+ // object tree assembly. The downside is that these methods will be empty
40
+ // for the leaf-level components.
41
+ //
42
+ // RU: В некоторых случаях целесообразно определить операции управления
43
+ // потомками прямо в базовом классе Компонент. Таким образом, вам не нужно
44
+ // будет предоставлять конкретные классы компонентов клиентскому коду, даже
45
+ // во время сборки дерева объектов. Недостаток такого подхода в том, что эти
46
+ // методы будут пустыми для компонентов уровня листа.
47
+ public virtual void Add ( Component component )
29
48
{
30
- children . Add ( component ) ;
49
+ throw new NotImplementedException ( ) ;
31
50
}
32
51
33
- public override void Remove ( Component component )
52
+ public virtual void Remove ( Component component )
34
53
{
35
- children . Remove ( component ) ;
54
+ throw new NotImplementedException ( ) ;
36
55
}
37
56
38
- public override bool IsComposite ( )
57
+ // EN: You can provide a method that lets the client code figure out whether
58
+ // a component can bear children.
59
+ //
60
+ // RU: Вы можете предоставить метод, который позволит клиентскому коду
61
+ // понять, может ли компонент иметь вложенные объекты.
62
+ public virtual bool IsComposite ( )
39
63
{
40
64
return true ;
41
65
}
66
+ }
42
67
43
- public override void Operation ( )
68
+ // EN: The Leaf class represents the end objects of a composition. A leaf can't
69
+ // have any children.
70
+ //
71
+ // Usually, it's the Leaf objects that do the actual work, whereas Composite
72
+ // objects only delegate to their sub-components.
73
+ //
74
+ // RU: Класс Лист представляет собой конечные объекты структуры. Лист не может
75
+ // иметь вложенных компонентов.
76
+ //
77
+ // Обычно объекты Листьев выполняют фактическую работу, тогда как объекты
78
+ // Контейнера лишь делегируют работу своим подкомпонентам.
79
+ class Leaf : Component
80
+ {
81
+ public override string Operation ( )
44
82
{
45
- int i = 0 ;
83
+ return "Leaf" ;
84
+ }
46
85
47
- Console . Write ( "Branch(" ) ;
48
- foreach ( Component component in children )
49
- {
50
- component . Operation ( ) ;
51
- if ( i != children . Count - 1 )
52
- {
53
- Console . Write ( "+" ) ;
54
- }
55
- i ++ ;
56
- }
57
- Console . Write ( ")" ) ;
86
+ public override bool IsComposite ( )
87
+ {
88
+ return false ;
58
89
}
59
90
}
60
91
61
- class Leaf : Component
92
+ // EN: The Composite class represents the complex components that may have
93
+ // children. Usually, the Composite objects delegate the actual work to their
94
+ // children and then "sum-up" the result.
95
+ //
96
+ // RU: Класс Контейнер содержит сложные компоненты, которые могут иметь
97
+ // вложенные компоненты. Обычно объекты Контейнеры делегируют фактическую работу
98
+ // своим детям, а затем «суммируют» результат.
99
+ class Composite : Component
62
100
{
63
- public Leaf ( )
101
+ protected List < Component > _children = new List < Component > ( ) ;
102
+
103
+ public override void Add ( Component component )
64
104
{
65
-
105
+ this . _children . Add ( component ) ;
66
106
}
67
107
68
- public override void Operation ( )
108
+ public override void Remove ( Component component )
69
109
{
70
- Console . Write ( "LEAF" ) ;
110
+ this . _children . Remove ( component ) ;
71
111
}
72
112
73
- public override void Add ( Component component )
113
+ // EN: The Composite executes its primary logic in a particular way. It
114
+ // traverses recursively through all its children, collecting and summing
115
+ // their results. Since the composite's children pass these calls to their
116
+ // children and so forth, the whole object tree is traversed as a result.
117
+ //
118
+ // RU: Контейнер выполняет свою основную логику особым образом. Он проходит
119
+ // рекурсивно через всех своих детей, собирая и суммируя их результаты.
120
+ // Поскольку потомки контейнера передают эти вызовы своим потомкам и так
121
+ // далее, в результате обходится всё дерево объектов.
122
+ public override string Operation ( )
74
123
{
75
- throw new NotImplementedException ( ) ;
124
+ int i = 0 ;
125
+ string result = "Branch(" ;
126
+
127
+ foreach ( Component component in this . _children )
128
+ {
129
+ result += component . Operation ( ) ;
130
+ if ( i != this . _children . Count - 1 )
131
+ {
132
+ result += "+" ;
133
+ }
134
+ i ++ ;
135
+ }
136
+
137
+ return result + ")" ;
76
138
}
139
+ }
77
140
78
- public override void Remove ( Component component )
141
+ class Client
142
+ {
143
+ // EN: The client code works with all of the components via the base
144
+ // interface.
145
+ //
146
+ // RU: Клиентский код работает со всеми компонентами через базовый
147
+ // интерфейс.
148
+ public void ClientCode ( Component leaf )
79
149
{
80
- throw new NotImplementedException ( ) ;
150
+ Console . WriteLine ( $ "RESULT: { leaf . Operation ( ) } \n " ) ;
81
151
}
82
152
83
- public override bool IsComposite ( )
153
+ // EN: Thanks to the fact that the child-management operations are
154
+ // declared in the base Component class, the client code can work with
155
+ // any component, simple or complex, without depending on their concrete
156
+ // classes.
157
+ //
158
+ // RU: Благодаря тому, что операции управления потомками объявлены в
159
+ // базовом классе Компонента, клиентский код может работать как с
160
+ // простыми, так и со сложными компонентами, вне зависимости от их
161
+ // конкретных классов.
162
+ public void ClientCode2 ( Component component1 , Component component2 )
84
163
{
85
- return false ;
164
+ if ( component1 . IsComposite ( ) )
165
+ {
166
+ component1 . Add ( component2 ) ;
167
+ }
168
+
169
+ Console . WriteLine ( $ "RESULT: { component1 . Operation ( ) } ") ;
86
170
}
87
171
}
88
-
89
- class Program
172
+
173
+ class Program
90
174
{
91
175
static void Main ( string [ ] args )
92
176
{
93
177
Client client = new Client ( ) ;
94
178
95
- Component leaf = new Leaf ( ) ;
179
+ // EN: This way the client code can support the simple leaf
180
+ // components...
181
+ //
182
+ // RU: Таким образом, клиентский код может поддерживать простые
183
+ // компоненты-листья...
184
+ Leaf leaf = new Leaf ( ) ;
96
185
Console . WriteLine ( "Client: I get a simple component:" ) ;
97
186
client . ClientCode ( leaf ) ;
98
- Console . WriteLine ( "\n " ) ;
99
187
188
+ // EN: ...as well as the complex composites.
189
+ //
190
+ // RU: ...а также сложные контейнеры.
100
191
Composite tree = new Composite ( ) ;
101
192
Composite branch1 = new Composite ( ) ;
102
193
branch1 . Add ( new Leaf ( ) ) ;
@@ -105,33 +196,11 @@ static void Main(string[] args)
105
196
branch2 . Add ( new Leaf ( ) ) ;
106
197
tree . Add ( branch1 ) ;
107
198
tree . Add ( branch2 ) ;
108
- Console . WriteLine ( "Client: Now I get a composite tree:" ) ;
199
+ Console . WriteLine ( "Client: Now I've got a composite tree:" ) ;
109
200
client . ClientCode ( tree ) ;
110
- Console . WriteLine ( "\n " ) ;
111
201
112
- Console . Write ( "Client: I can merge two components without checking their classes :\n " ) ;
202
+ Console . Write ( "Client: I don't need to check the components classes even when managing the tree :\n " ) ;
113
203
client . ClientCode2 ( tree , leaf ) ;
114
204
}
115
205
}
116
-
117
- class Client
118
- {
119
- public void ClientCode ( Component leaf )
120
- {
121
- Console . Write ( "RESULT: " ) ;
122
- leaf . Operation ( ) ;
123
- }
124
-
125
- public void ClientCode2 ( Component component1 , Component component2 )
126
- {
127
- if ( component1 . IsComposite ( ) )
128
- {
129
- component1 . Add ( component2 ) ;
130
- }
131
- Console . Write ( "RESULT: " ) ;
132
- component1 . Operation ( ) ;
133
-
134
- Console . WriteLine ( ) ;
135
- }
136
- }
137
206
}
0 commit comments