Skip to content

Commit 8d1ebf5

Browse files
authored
Merge pull request #21 from ilopX/add-observer-example-for-further-use-in-more-complex-examples
Add example "Observer" for later use in more complex examples.
2 parents 3a98693 + eeb4798 commit 8d1ebf5

File tree

16 files changed

+311
-3
lines changed

16 files changed

+311
-3
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.dart_tool/
22
.idea/
33
build/
4+
windows/
45

56
.packages
67
pubspec.lock

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 0.15.0
2+
- Add second "Observer" example. This example was created to be used in a more complex example.
3+
14
## 0.14.0
25
- Add "Memento" conceptual pattern
36

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ It contains **Dart** examples for all classic **GoF** design patterns.
1515
- [ ] Interpreter
1616
- [ ] [**Iterator**](https://refactoring.guru/design-patterns/iterator)
1717
- [ ] [**Mediator**](https://refactoring.guru/design-patterns/mediator)
18-
- [x] [**Memento**](https://refactoring.guru/design-patterns/memento) [[Conceptual](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/memento/conceptual)]
19-
- [x] [**Observer**](https://refactoring.guru/design-patterns/observer) - [[Open-Close Editor Events](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/open_close_editor_events)]
18+
- [x] [**Memento**](https://refactoring.guru/design-patterns/memento) - [[Conceptual](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/memento/conceptual)]
19+
- [x] [**Observer**](https://refactoring.guru/design-patterns/observer) - [[Open-Close Editor Events](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/open_close_editor_events)] [[AppObserver](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/app_observer)]
2020
- [ ] [**State**](https://refactoring.guru/design-patterns/state)
2121
- [ ] [**Template Method**](https://refactoring.guru/design-patterns/template-method)
2222
- [ ] [**Visitor**](https://refactoring.guru/design-patterns/visitor)

bin/main.dart

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import 'package:flutter/material.dart';
2+
3+
void main() {
4+
runApp(const MyApp());
5+
}
6+
7+
class MyApp extends StatelessWidget {
8+
const MyApp({Key? key}) : super(key: key);
9+
10+
@override
11+
Widget build(BuildContext context) {
12+
return MaterialApp(
13+
title: 'Refactoring Guru: Flutter launcher',
14+
theme: ThemeData(
15+
primarySwatch: Colors.pink
16+
),
17+
home: Container(),
18+
);
19+
}
20+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Observer pattern
2+
Observer is a behavioral design pattern that lets you define a subscription mechanism to notify
3+
multiple objects about any events that happen to the object they’re observing.
4+
5+
Tutorial: [here](https://refactoring.guru/design-patterns/observer).
6+
7+
## AppObserver example
8+
This example was created to be used in a more complex example.
9+
A complex example will be implemented later.
10+
11+
### Diagram:
12+
![image](https://user-images.githubusercontent.com/8049534/152049751-b111e02a-1d33-4796-810c-b7ed069cecdc.png)
13+
14+
### Sequence
15+
![image](https://user-images.githubusercontent.com/8049534/152049996-72131655-402d-4b92-b5d0-10e3f2dd0e79.png)
16+
17+
### Client code:
18+
```dart
19+
void main() {
20+
final observer = AppObserver();
21+
22+
observer.subscribe<FirstEvent>((e) {
23+
print('First');
24+
});
25+
26+
27+
observer.subscribe((SecondEvent e) {
28+
print('Second');
29+
});
30+
31+
final saveThirdEvent = observer.subscribe((ThirdEvent e) {
32+
print('Third');
33+
});
34+
35+
observer.notify(FirstEvent());
36+
observer.notify(SecondEvent());
37+
observer.notify(ThirdEvent());
38+
39+
print('---unsubscribe "ThirdEvent"---');
40+
observer.unsubscribe(saveThirdEvent);
41+
42+
observer.notify(FirstEvent());
43+
observer.notify(SecondEvent());
44+
observer.notify(ThirdEvent());
45+
}
46+
```
47+
48+
**Output:**
49+
```
50+
First
51+
Second
52+
Third
53+
---unsubscribe "ThirdEvent"---
54+
First
55+
Second
56+
```
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import 'observer/app_observer.dart';
2+
import 'observer/event.dart';
3+
4+
class FirstEvent extends Event {}
5+
6+
class SecondEvent extends Event {}
7+
8+
class ThirdEvent extends Event {}
9+
10+
void main() {
11+
final observer = AppObserver();
12+
13+
observer.subscribe<FirstEvent>((e) {
14+
print('First');
15+
});
16+
17+
18+
observer.subscribe((SecondEvent e) {
19+
print('Second');
20+
});
21+
22+
final saveThirdEvent = observer.subscribe((ThirdEvent e) {
23+
print('Third');
24+
});
25+
26+
observer.notify(FirstEvent());
27+
observer.notify(SecondEvent());
28+
observer.notify(ThirdEvent());
29+
30+
print('---unsubscribe "ThirdEvent"---');
31+
observer.unsubscribe(saveThirdEvent);
32+
33+
observer.notify(FirstEvent());
34+
observer.notify(SecondEvent());
35+
observer.notify(ThirdEvent());
36+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import 'event.dart';
2+
3+
typedef EventFunction<T> = void Function(T e);
4+
5+
class AppObserver {
6+
final _subscribers = <int, List<dynamic>>{};
7+
8+
EventFunction<T> subscribe<T>(EventFunction<T> func) {
9+
assert(
10+
Class<T>() is Class<Event>,
11+
'\n\nThe callback argument must implement the "Event" class.\n'
12+
'Correct use: \n'
13+
'\tobserver.subscribe((MyEvent e) {}); \n'
14+
'Mistaken usage: \n'
15+
'\tobserver.subscribe((String e) {});\n'
16+
'\tobserver.subscribe((e) {});\n',
17+
);
18+
19+
_subscribers.putIfAbsent(T.hashCode, () => []).add(func);
20+
return func;
21+
}
22+
23+
void unsubscribe<T extends Event>(EventFunction<T> func) {
24+
final isDelete = _subscribers[T.hashCode]?.remove(func) ?? false;
25+
26+
if (isDelete) {
27+
return;
28+
}
29+
30+
throw Exception('Subscriber not found.');
31+
}
32+
33+
void notify<T extends Event>(T event) {
34+
final subscribers = _subscribers[T.hashCode];
35+
36+
if (subscribers == null) {
37+
return;
38+
}
39+
40+
for (var sub in subscribers) {
41+
sub.call(event);
42+
}
43+
}
44+
}
45+
46+
class Class<T> {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
abstract class Event {
2+
3+
}

pubspec.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: design_patterns_dart
22
description: Dart examples for all classic GoF design patterns.
3-
version: 0.14.0
3+
version: 0.15.0
44
homepage: https://refactoring.guru/design-patterns
55
repository: https://github.com/RefactoringGuru/design-patterns-dart
66
issue_tracker: https://github.com/RefactoringGuru/design-patterns-dart/issue
@@ -10,6 +10,10 @@ environment:
1010

1111
dependencies:
1212
collection: ^1.15.0
13+
flutter:
14+
sdk: flutter
1315

1416
dev_dependencies:
1517
lints: ^1.0.0
18+
19+

web/favicon.png

917 Bytes
Loading

0 commit comments

Comments
 (0)