Skip to content

Commit f7886f0

Browse files
committed
Add "Observer" pattern. Official example from java.
1 parent 6d145e9 commit f7886f0

File tree

7 files changed

+164
-0
lines changed

7 files changed

+164
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
## Editor example
6+
In this example, the Observer pattern lets the text editor object notify other service objects about
7+
changes in its state.
8+
9+
More detailed explanation on [RefactoringGuru](https://refactoring.guru/design-patterns/observer?#pseudocode).
10+
11+
### Origin source code:
12+
This example rewrite from [java example](https://github.com/RefactoringGuru/design-patterns-java/tree/master/src/refactoring_guru/observer/example).
13+
14+
### Diagram:
15+
![image](https://user-images.githubusercontent.com/8049534/150955865-7fbb29f3-ed48-4317-a356-cbb9cc79ed11.png)
16+
17+
### Client code:
18+
```dart
19+
void main() {
20+
final editor = Editor();
21+
editor.events
22+
..subscribe(
23+
'open',
24+
LogOpenListener('log.txt'),
25+
)
26+
..subscribe(
27+
'save',
28+
EmailNotificationListener('admin@example.com'),
29+
);
30+
31+
try {
32+
editor.openFile('test.txt');
33+
editor.saveFile();
34+
} catch (e) {
35+
print(e);
36+
}
37+
}
38+
```
39+
40+
**Output:**
41+
```
42+
Save to log "log.txt": Someone has performed "open" operation with the following file: "test.txt"
43+
Email to "admin@example.com": Someone has performed "save" operation with the following file: "test.txt"
44+
```
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import 'dart:io';
2+
3+
import '../event_manager/event_manager.dart';
4+
5+
class Editor {
6+
final events = EventManager(['open', 'save']);
7+
8+
File? _file;
9+
10+
void openFile(String filePath) {
11+
_file = File(filePath);
12+
events.notify("open", _file!);
13+
}
14+
15+
void saveFile() {
16+
if (_file == null) {
17+
throw Exception('Please open a file first.');
18+
}
19+
20+
events.notify('save', _file!);
21+
}
22+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import 'dart:io';
2+
3+
import '../listeners/event_listener.dart';
4+
5+
class EventManager {
6+
final _listeners = <String, List<EventListener>>{};
7+
8+
EventManager(List<String> operations) {
9+
for (final operation in operations) {
10+
_listeners[operation] = [];
11+
}
12+
}
13+
14+
void subscribe(String eventType, EventListener listener) {
15+
_usersBy(eventType).add(listener);
16+
}
17+
18+
void unsubscribe(String eventType, EventListener listener) {
19+
_usersBy(eventType).remove(listener);
20+
}
21+
22+
void notify(String eventType, File file) {
23+
final users = _usersBy(eventType);
24+
for (final listener in users) {
25+
listener.update(eventType, file);
26+
}
27+
}
28+
29+
List<EventListener> _usersBy(String eventType) {
30+
final users = _listeners[eventType];
31+
32+
if (users == null) {
33+
throw UnsupportedError('Event type "$eventType" do not support.');
34+
}
35+
36+
return users;
37+
}
38+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import 'dart:io';
2+
3+
import 'event_listener.dart';
4+
5+
class EmailNotificationListener implements EventListener {
6+
String email;
7+
8+
EmailNotificationListener(this.email);
9+
10+
@override
11+
void update(String eventType, File file) {
12+
print('Email to "$email": '
13+
'Someone has performed "$eventType" '
14+
'operation with the following file: "${file.path}"');
15+
}
16+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import 'dart:io';
2+
3+
abstract class EventListener {
4+
void update(String eventType, File file);
5+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import 'dart:io';
2+
3+
import 'event_listener.dart';
4+
5+
class LogOpenListener implements EventListener {
6+
File logFile;
7+
8+
LogOpenListener(String logFileName) : logFile = File(logFileName);
9+
10+
@override
11+
void update(String eventType, File file) {
12+
print('Save to log "${logFile.path}": '
13+
'Someone has performed "$eventType" '
14+
'operation with the following file: "${file.path}"');
15+
}
16+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import 'editor/editor.dart';
2+
import 'listeners/email_notification_listener.dart';
3+
import 'listeners/log_open_listener.dart';
4+
5+
void main() {
6+
final editor = Editor();
7+
editor.events
8+
..subscribe(
9+
'open',
10+
LogOpenListener('log.txt'),
11+
)
12+
..subscribe(
13+
'save',
14+
EmailNotificationListener('admin@example.com'),
15+
);
16+
17+
try {
18+
editor.openFile('test.txt');
19+
editor.saveFile();
20+
} catch (e) {
21+
print(e);
22+
}
23+
}

0 commit comments

Comments
 (0)