-
Notifications
You must be signed in to change notification settings - Fork 124
Expand file tree
/
Copy pathmain.cc
More file actions
171 lines (158 loc) · 7.48 KB
/
main.cc
File metadata and controls
171 lines (158 loc) · 7.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <array>
#include <iostream>
#include <string>
/**
* EN: Visitor Design Pattern
*
* Intent: Lets you separate algorithms from the objects on which they operate.
*
* RU: Паттерн Посетитель
*
* Назначение: Позволяет создавать новые операции, не меняя классы объектов, над
* которыми эти операции могут выполняться.
*/
/**
* EN: The Visitor Interface declares a set of visiting methods that correspond
* to component classes. The signature of a visiting method allows the visitor
* to identify the exact class of the component that it's dealing with.
*
* RU: Интерфейс Посетителя объявляет набор методов посещения, соответствующих
* классам компонентов. Сигнатура метода посещения позволяет посетителю
* определить конкретный класс компонента, с которым он имеет дело.
*/
class ConcreteComponentA;
class ConcreteComponentB;
class Visitor {
public:
virtual ~Visitor() = default;
virtual void VisitConcreteComponentA(const ConcreteComponentA *element) const = 0;
virtual void VisitConcreteComponentB(const ConcreteComponentB *element) const = 0;
};
/**
* EN: The Component interface declares an `accept` method that should take the
* base visitor interface as an argument.
*
* RU: Интерфейс Компонента объявляет метод accept, который в качестве аргумента
* может получать любой объект, реализующий интерфейс посетителя.
*/
class Component {
public:
virtual ~Component() {}
virtual void Accept(Visitor *visitor) const = 0;
};
/**
* EN: Each Concrete Component must implement the `Accept` method in such a way
* that it calls the visitor's method corresponding to the component's class.
*
* RU: Каждый Конкретный Компонент должен реализовать метод accept таким
* образом, чтобы он вызывал метод посетителя, соответствующий классу
* компонента.
*/
class ConcreteComponentA : public Component {
/**
* EN: Note that we're calling `visitConcreteComponentA`, which matches the
* current class name. This way we let the visitor know the class of the
* component it works with.
*
* RU: Обратите внимание, мы вызываем visitConcreteComponentA, что
* соответствует названию текущего класса. Таким образом мы позволяем
* посетителю узнать, с каким классом компонента он работает.
*/
public:
void Accept(Visitor *visitor) const override {
visitor->VisitConcreteComponentA(this);
}
/**
* EN: Concrete Components may have special methods that don't exist in
* their base class or interface. The Visitor is still able to use these
* methods since it's aware of the component's concrete class.
*
* RU: Конкретные Компоненты могут иметь особые методы, не объявленные в их
* базовом классе или интерфейсе. Посетитель всё же может использовать эти
* методы, поскольку он знает о конкретном классе компонента.
*/
std::string ExclusiveMethodOfConcreteComponentA() const {
return "A";
}
};
class ConcreteComponentB : public Component {
/**
* EN: Same here: visitConcreteComponentB => ConcreteComponentB
*
* RU: То же самое здесь: visitConcreteComponentB => ConcreteComponentB
*/
public:
void Accept(Visitor *visitor) const override {
visitor->VisitConcreteComponentB(this);
}
std::string SpecialMethodOfConcreteComponentB() const {
return "B";
}
};
/**
* EN: Concrete Visitors implement several versions of the same algorithm, which
* can work with all concrete component classes.
*
* You can experience the biggest benefit of the Visitor pattern when using it
* with a complex object structure, such as a Composite tree. In this case, it
* might be helpful to store some intermediate state of the algorithm while
* executing visitor's methods over various objects of the structure.
*
* RU: Конкретные Посетители реализуют несколько версий одного и того же
* алгоритма, которые могут работать со всеми классами конкретных компонентов.
*
* Максимальную выгоду от паттерна Посетитель вы почувствуете, используя его со
* сложной структурой объектов, такой как дерево Компоновщика. В этом случае
* было бы полезно хранить некоторое промежуточное состояние алгоритма при
* выполнении методов посетителя над различными объектами структуры.
*/
class ConcreteVisitor1 : public Visitor {
public:
void VisitConcreteComponentA(const ConcreteComponentA *element) const override {
std::cout << element->ExclusiveMethodOfConcreteComponentA() << " + ConcreteVisitor1\n";
}
void VisitConcreteComponentB(const ConcreteComponentB *element) const override {
std::cout << element->SpecialMethodOfConcreteComponentB() << " + ConcreteVisitor1\n";
}
};
class ConcreteVisitor2 : public Visitor {
public:
void VisitConcreteComponentA(const ConcreteComponentA *element) const override {
std::cout << element->ExclusiveMethodOfConcreteComponentA() << " + ConcreteVisitor2\n";
}
void VisitConcreteComponentB(const ConcreteComponentB *element) const override {
std::cout << element->SpecialMethodOfConcreteComponentB() << " + ConcreteVisitor2\n";
}
};
/**
* EN: The client code can run visitor operations over any set of elements
* without figuring out their concrete classes. The accept operation directs a
* call to the appropriate operation in the visitor object.
*
* RU: Клиентский код может выполнять операции посетителя над любым набором
* элементов, не выясняя их конкретных классов. Операция принятия направляет
* вызов к соответствующей операции в объекте посетителя.
*/
void ClientCode(std::array<const Component *, 2> components, Visitor *visitor) {
// ...
for (const Component *comp : components) {
comp->Accept(visitor);
}
// ...
}
int main() {
std::array<const Component *, 2> components = {new ConcreteComponentA, new ConcreteComponentB};
std::cout << "The client code works with all visitors via the base Visitor interface:\n";
ConcreteVisitor1 *visitor1 = new ConcreteVisitor1;
ClientCode(components, visitor1);
std::cout << "\n";
std::cout << "It allows the same client code to work with different types of visitors:\n";
ConcreteVisitor2 *visitor2 = new ConcreteVisitor2;
ClientCode(components, visitor2);
for (const Component *comp : components) {
delete comp;
}
delete visitor1;
delete visitor2;
return 0;
}