Skip to content

Commit e439cad

Browse files
committed
Visitor: improve conceptual example
1 parent 4d8ba56 commit e439cad

File tree

1 file changed

+89
-22
lines changed

1 file changed

+89
-22
lines changed

Visitor.Conceptual/Program.cs

Lines changed: 89 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,146 @@
1-
using System;
1+
// EN: Visitor Design Pattern
2+
//
3+
// Intent: Represent an operation to be performed over elements of an object
4+
// structure. The Visitor pattern lets you define a new operation without
5+
// changing the classes of the elements on which it operates.
6+
//
7+
// RU: Паттерн Посетитель
8+
//
9+
// Назначение: Позволяет добавлять в программу новые операции, не изменяя классы
10+
// объектов, над которыми эти операции могут выполняться.
11+
12+
using System;
213
using System.Collections.Generic;
314

415
namespace RefactoringGuru.DesignPatterns.Visitor.Conceptual
516
{
6-
interface Component
17+
// EN: The Component interface declares an `accept` method that should take the
18+
// base visitor interface as an argument.
19+
//
20+
// RU: Интерфейс Компонента объявляет метод accept, который в качестве
21+
// аргумента может получать любой объект, реализующий интерфейс посетителя.
22+
public interface Component
723
{
8-
void accept(Visitor visitor);
24+
void Accept(Visitor visitor);
925
}
1026

27+
// EN: Each Concrete Component must implement the `Accept` method in such a way
28+
// that it calls the visitor's method corresponding to the component's class.
29+
//
30+
// RU: Каждый Конкретный Компонент должен реализовать метод Accept таким
31+
// образом, чтобы он вызывал метод посетителя, соответствующий классу компонента.
1132
public class ConcreteComponentA : Component
1233
{
13-
public void accept(Visitor visitor)
34+
// EN: Note that we're calling `VisitConcreteComponentA`, which matches the
35+
// current class name. This way we let the visitor know the class of the
36+
// component it works with.
37+
//
38+
// RU: Обратите внимание, мы вызываем VisitConcreteComponentA, что
39+
// соответствует названию текущего класса. Таким образом мы позволяем
40+
// посетителю узнать, с каким классом компонента он работает.
41+
public void Accept(Visitor visitor)
1442
{
15-
visitor.visitConcreteComponentA(this);
43+
visitor.VisitConcreteComponentA(this);
1644
}
1745

18-
public string exclusiveMethodOfConcreteComponentA()
46+
// EN: Concrete Components may have special methods that don't exist in
47+
// their base class or interface. The Visitor is still able to use these
48+
// methods since it's aware of the component's concrete class.
49+
//
50+
// RU: Конкретные Компоненты могут иметь особые методы, не объявленные в их
51+
// базовом классе или интерфейсе. Посетитель всё же может использовать эти
52+
// методы, поскольку он знает о конкретном классе компонента.
53+
public string ExclusiveMethodOfConcreteComponentA()
1954
{
2055
return "A";
2156
}
2257
}
2358

2459
public class ConcreteComponentB : Component
2560
{
26-
public void accept(Visitor visitor)
61+
// EN: Same here: VisitConcreteComponentB => ConcreteComponentB
62+
//
63+
// RU: То же самое здесь: VisitConcreteComponentB => ConcreteComponentB
64+
public void Accept(Visitor visitor)
2765
{
28-
visitor.visitConcreteComponentB(this);
66+
visitor.VisitConcreteComponentB(this);
2967
}
3068

31-
public string specialMethodOfConcreteComponentB()
69+
public string SpecialMethodOfConcreteComponentB()
3270
{
3371
return "B";
3472
}
3573
}
3674

75+
// EN: The Visitor Interface declares a set of visiting methods that correspond
76+
// to component classes. The signature of a visiting method allows the visitor
77+
// to identify the exact class of the component that it's dealing with.
78+
//
79+
// RU: Интерфейс Посетителя объявляет набор методов посещения, соответствующих
80+
// классам компонентов. Сигнатура метода посещения позволяет посетителю
81+
// определить конкретный класс компонента, с которым он имеет дело.
3782
public interface Visitor
3883
{
39-
void visitConcreteComponentA(ConcreteComponentA el);
84+
void VisitConcreteComponentA(ConcreteComponentA element);
4085

41-
void visitConcreteComponentB(ConcreteComponentB el);
86+
void VisitConcreteComponentB(ConcreteComponentB element);
4287
}
4388

89+
// EN: Concrete Visitors implement several versions of the same algorithm, which
90+
// can work with all concrete component classes.
91+
//
92+
// You can experience the biggest benefit of the Visitor pattern when using it
93+
// with a complex object structure, such as a Composite tree. In this case, it
94+
// might be helpful to store some intermediate state of the algorithm while
95+
// executing visitor's methods over various objects of the structure.
96+
//
97+
// RU: Конкретные Посетители реализуют несколько версий одного и того же
98+
// алгоритма, которые могут работать со всеми классами конкретных компонентов.
99+
//
100+
// Максимальную выгоду от паттерна Посетитель вы почувствуете, используя его со
101+
// сложной структурой объектов, такой как дерево Компоновщика. В этом случае
102+
// было бы полезно хранить некоторое промежуточное состояние алгоритма при
103+
// выполнении методов посетителя над различными объектами структуры.
44104
class ConcreteVisitor1 : Visitor
45105
{
46-
public void visitConcreteComponentA(ConcreteComponentA el)
106+
public void VisitConcreteComponentA(ConcreteComponentA element)
47107
{
48-
Console.Write(el.exclusiveMethodOfConcreteComponentA() + " + ConcreteVisitor1\n");
108+
Console.WriteLine(element.ExclusiveMethodOfConcreteComponentA() + " + ConcreteVisitor1");
49109
}
50110

51-
public void visitConcreteComponentB(ConcreteComponentB el)
111+
public void VisitConcreteComponentB(ConcreteComponentB element)
52112
{
53-
Console.Write(el.specialMethodOfConcreteComponentB() + " + ConcreteVisitor1\n");
113+
Console.WriteLine(element.SpecialMethodOfConcreteComponentB() + " + ConcreteVisitor1");
54114
}
55115
}
56116

57117
class ConcreteVisitor2 : Visitor
58118
{
59-
public void visitConcreteComponentA(ConcreteComponentA el)
119+
public void VisitConcreteComponentA(ConcreteComponentA element)
60120
{
61-
Console.Write(el.exclusiveMethodOfConcreteComponentA() + " + ConcreteVisitor2\n");
121+
Console.WriteLine(element.ExclusiveMethodOfConcreteComponentA() + " + ConcreteVisitor2");
62122
}
63123

64-
public void visitConcreteComponentB(ConcreteComponentB el)
124+
public void VisitConcreteComponentB(ConcreteComponentB element)
65125
{
66-
Console.Write(el.specialMethodOfConcreteComponentB() + " + ConcreteVisitor2\n");
126+
Console.WriteLine(element.SpecialMethodOfConcreteComponentB() + " + ConcreteVisitor2");
67127
}
68128
}
69129

70-
internal class Client
130+
public class Client
71131
{
72-
internal static void ClientCode(List<Component> components, Visitor visitor)
132+
// EN: The client code can run visitor operations over any set of elements
133+
// without figuring out their concrete classes. The accept operation directs a
134+
// call to the appropriate operation in the visitor object.
135+
//
136+
// RU: Клиентский код может выполнять операции посетителя над любым набором
137+
// элементов, не выясняя их конкретных классов. Операция принятия направляет
138+
// вызов к соответствующей операции в объекте посетителя.
139+
public static void ClientCode(List<Component> components, Visitor visitor)
73140
{
74141
foreach (var component in components)
75142
{
76-
component.accept(visitor);
143+
component.Accept(visitor);
77144
}
78145
}
79146
}

0 commit comments

Comments
 (0)