Skip to content

Commit ec43b4b

Browse files
authored
Merge pull request #46 from ilopX/add-visitor-pattern
Add visitor pattern.
2 parents 50a9d80 + 5ffb387 commit ec43b4b

File tree

12 files changed

+302
-3
lines changed

12 files changed

+302
-3
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 0.22.0
2+
- Add visitor pattern: "Shape Xml Export".
3+
14
## 0.21.0
25
- Add strategy pattern: "Reservation cargo spaces".
36

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ It contains **Dart** examples for all classic **GoF** design patterns.
1919
- [x] **Observer** - [[Open-Close Editor Events](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/observer/open_close_editor_events)] [[AppObserver](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/observer/app_observer)] [[Subscriber Flutter Widget](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/observer/subscriber_flutter_widget)]
2020
- [ ] **State**
2121
- [ ] **Template Method**
22-
- [ ] **Visitor**
23-
- [X] **Strategy** [[Reservation cargo spaces](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/strategy/reservation_cargo_spaces)]
22+
- [X] **Visitor** [[Shape XML Exporter](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/visitor/shapes_exporter)]
23+
- [X] **Strategy** [[Reservation Cargo Spaces](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/strategy/reservation_cargo_spaces)]
2424
- [ ] **Structural**
2525
- [x] **Adapter** - [[Text Graphics](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/adapter/text_graphics)] [[Square Round conflict](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/adapter/square_round_conflict)] [[Flutter Adapter](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/adapter/flutter_adapter)]
2626
- [x] **Bridge** - [[Remote Device Control](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/bridge/devices_remote_control)] [[Clock](https://github.com/RefactoringGuru/design-patterns-dart/tree/main/patterns/bridge/clock)]
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Visitor pattern
2+
Visitor is a behavioral design pattern that lets you separate algorithms from the objects on which
3+
they operate.
4+
5+
Tutorial: [here](https://refactoring.guru/design-patterns/visitor).
6+
7+
### About example: Shape XML Exporter.
8+
In this example, the Visitor pattern adds XML export support to the class hierarchy of geometric
9+
shapes [More info](https://refactoring.guru/design-patterns/visitor#pseudocode).
10+
11+
This example rewrite from original source code [java example](https://github.com/RefactoringGuru/design-patterns-java/tree/main/src/refactoring_guru/visitor/example)
12+
13+
### Diagram:
14+
![image](https://user-images.githubusercontent.com/8049534/167304227-04237030-879e-4d7f-be32-4c815a3e1cbf.png)
15+
16+
### Client code:
17+
```dart
18+
final compoundShape = CompoundShape(
19+
x: 30,
20+
y: 45,
21+
children: [
22+
Rectangle(x: 10, y: 10, width: 100, height: 100),
23+
Circle(xCenter: 300, yCenter: 20, radius: 35),
24+
Dot(x: 60, y: 60),
25+
CompoundShape(
26+
x: 5,
27+
y: 5,
28+
children: [
29+
Dot(x: 15, y: 15),
30+
Dot(x: 20, y: 20),
31+
],
32+
),
33+
],
34+
);
35+
36+
final xml = XMLExportVisitor().export(compoundShape);
37+
print(xml);
38+
```
39+
40+
### Output:
41+
```xml
42+
<?xml version="1.0" encoding="utf-8"?>
43+
<compound>
44+
<x>30</x>
45+
<y>45</y>
46+
<children>
47+
<rectangle>
48+
<x>10</x>
49+
<y>10</y>
50+
<width>100</width>
51+
<height>100</height>
52+
</rectangle>
53+
<circle>
54+
<xCenter>300</xCenter>
55+
<yCenter>20</yCenter>
56+
<radius>35</radius>
57+
</circle>
58+
<dot>
59+
<x>60</x>
60+
<y>60</y>
61+
</dot>
62+
<compound>
63+
<x>5</x>
64+
<y>5</y>
65+
<children>
66+
<dot>
67+
<x>15</x>
68+
<y>15</y>
69+
</dot>
70+
<dot>
71+
<x>20</x>
72+
<y>20</y>
73+
</dot>
74+
</children>
75+
</compound>
76+
</children>
77+
</compound>
78+
```
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import 'shapes/circle.dart';
2+
import 'shapes/compound_shape.dart';
3+
import 'shapes/dot.dart';
4+
import 'shapes/rectangle.dart';
5+
import 'visitor/xml_export_visitor.dart';
6+
7+
void main() {
8+
final compoundShape = CompoundShape(
9+
x: 30,
10+
y: 45,
11+
children: [
12+
Rectangle(x: 10, y: 10, width: 100, height: 100),
13+
Circle(xCenter: 300, yCenter: 20, radius: 35),
14+
Dot(x: 60, y: 60),
15+
CompoundShape(
16+
x: 5,
17+
y: 5,
18+
children: [
19+
Dot(x: 15, y: 15),
20+
Dot(x: 20, y: 20),
21+
],
22+
),
23+
],
24+
);
25+
26+
final xml = XMLExportVisitor().export(compoundShape);
27+
print(xml);
28+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import '../visitor/visitor.dart';
2+
import 'shape.dart';
3+
4+
class Circle implements Shape {
5+
final int xCenter;
6+
final int yCenter;
7+
final int radius;
8+
9+
Circle({
10+
required this.xCenter,
11+
required this.yCenter,
12+
required this.radius,
13+
});
14+
15+
@override
16+
void accept(Visitor visitor) {
17+
visitor.visitCircle(this);
18+
}
19+
20+
@override
21+
void draw() {
22+
// ...
23+
}
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import '../visitor/visitor.dart';
2+
import 'shape.dart';
3+
4+
class CompoundShape implements Shape {
5+
final int x;
6+
final int y;
7+
final List<Shape> children;
8+
9+
CompoundShape({
10+
required this.x,
11+
required this.y,
12+
required this.children,
13+
});
14+
15+
@override
16+
void accept(Visitor visitor) {
17+
visitor.visitCompoundShape(this);
18+
}
19+
20+
@override
21+
void draw() {
22+
// ...
23+
}
24+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import '../visitor/visitor.dart';
2+
import 'shape.dart';
3+
4+
class Dot implements Shape {
5+
final int x;
6+
final int y;
7+
8+
Dot({
9+
required this.x,
10+
required this.y,
11+
});
12+
13+
@override
14+
void accept(Visitor visitor) {
15+
visitor.visitDot(this);
16+
}
17+
18+
@override
19+
void draw() {
20+
// ...
21+
}
22+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import '../visitor/visitor.dart';
2+
import 'shape.dart';
3+
4+
class Rectangle implements Shape {
5+
final int x;
6+
final int y;
7+
final int width;
8+
final int height;
9+
10+
Rectangle({
11+
required this.x,
12+
required this.y,
13+
required this.width,
14+
required this.height,
15+
});
16+
17+
@override
18+
void accept(Visitor visitor) {
19+
visitor.visitRectangle(this);
20+
}
21+
22+
@override
23+
void draw() {
24+
// ...
25+
}
26+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import '../visitor/visitor.dart';
2+
3+
abstract class Shape {
4+
void accept(Visitor visitor);
5+
6+
void draw();
7+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import '../shapes/circle.dart';
2+
import '../shapes/compound_shape.dart';
3+
import '../shapes/dot.dart';
4+
import '../shapes/rectangle.dart';
5+
6+
abstract class Visitor {
7+
void visitCompoundShape(CompoundShape compound);
8+
9+
void visitDot(Dot dot);
10+
11+
void visitCircle(Circle circle);
12+
13+
void visitRectangle(Rectangle rectangle);
14+
}

0 commit comments

Comments
 (0)