Skip to content

Commit a212519

Browse files
authored
Merge pull request #22 from ilopX/observer-pattern-example-flutter-subscriber-widget
Add complex example of Observer pattern, connected to Flutter application.
2 parents 8d1ebf5 + 6b05f19 commit a212519

File tree

12 files changed

+318
-93
lines changed

12 files changed

+318
-93
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.16.0
2+
- Add complex example of an Observer pattern, connected to a Flutter application.
3+
- Add new branch "web-demos" for online examples.
4+
15
## 0.15.0
26
- Add second "Observer" example. This example was created to be used in a more complex example.
37

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ It contains **Dart** examples for all classic **GoF** design patterns.
1616
- [ ] [**Iterator**](https://refactoring.guru/design-patterns/iterator)
1717
- [ ] [**Mediator**](https://refactoring.guru/design-patterns/mediator)
1818
- [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)]
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)] [[Subscriber Flutter Widget](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/subscriber_flutter_widget)]
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)
@@ -33,6 +33,7 @@ It contains **Dart** examples for all classic **GoF** design patterns.
3333
## Requirements
3434

3535
The examples were written in **Dart 2.15**.
36+
Some complex examples require **Flutter 2.15.0**.
3637

3738
## Contributor's Guide
3839

@@ -65,6 +66,12 @@ Here's a style guide which might help you to keep your changes consistent with o
6566
Don't be scared and ignore the non-English part of such comments. If you want to change something in a comment like this, then do it. Even if you do it wrong, we'll tell you how to fix it during the Pull Request.
6667
6768
69+
### Build Flutter examples
70+
```batch
71+
cd root directory
72+
flutter build web -t bin\main.dart --web-renderer html
73+
```
74+
6875
## License
6976

7077
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.

bin/main.dart

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import 'package:flutter/material.dart';
2+
import '../patterns/observer/subscriber_flutter_widget/main.dart';
23

34
void main() {
4-
runApp(const MyApp());
5+
runApp(MyApp());
56
}
67

78
class MyApp extends StatelessWidget {
@@ -11,10 +12,11 @@ class MyApp extends StatelessWidget {
1112
Widget build(BuildContext context) {
1213
return MaterialApp(
1314
title: 'Refactoring Guru: Flutter launcher',
14-
theme: ThemeData(
15-
primarySwatch: Colors.pink
16-
),
17-
home: Container(),
15+
theme: ThemeData(primarySwatch: Colors.pink),
16+
initialRoute: '/observer/subscriber_flutter_widget',
17+
routes: {
18+
'/observer/subscriber_flutter_widget': (_) => SubscriberFlutterApp(),
19+
},
1820
);
1921
}
2022
}
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+
Tutorial: [here](https://refactoring.guru/design-patterns/observer).
6+
7+
## Subscriber Flutter Widget example
8+
This is a complex example of an Observer pattern, connected to a Flutter application. The example includes,
9+
the previously implemented **AppObserver** example pattern, which you can see [here](https://github.com/RefactoringGuru/design-patterns-dart/tree/master/patterns/observer/app_observer).
10+
11+
### Diagram:
12+
![image](https://user-images.githubusercontent.com/8049534/152418114-f040bcb4-3bf5-4581-8b9b-a264e103ff76.png)
13+
14+
### Sequence
15+
![image](https://user-images.githubusercontent.com/8049534/152418299-3f6f3e5d-7132-42bc-9b27-11ed53ca6434.png)
16+
17+
### Client code:
18+
```dart
19+
void main() {
20+
// widget that generates a new event
21+
ElevatedButton(
22+
child: Text('Generate new hash'),
23+
onPressed: () {
24+
final hash = 'some hash';
25+
observer.notify(NewHashEvent(hash));
26+
},
27+
);
28+
29+
// widget event consumer NewHashEvent
30+
SubscriberWidget<NewHashEvent>(
31+
observer: observer,
32+
builder: (context, event) {
33+
return Text(
34+
event?.newHash ?? 'Hash no generated' ,
35+
);
36+
},
37+
);
38+
}
39+
```
40+
41+
### Online demo:
42+
Click on the picture to see a [demo](https://ilopx.github.io/design-patterns-dart/#/observer/subscriber_flutter_widget).
43+
44+
[![image](https://user-images.githubusercontent.com/8049534/152419178-f40a07fd-728d-4f99-befa-0935bbdd7b71.png)](https://ilopx.github.io/design-patterns-dart/#/observer/subscriber_flutter_widget)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import '../../app_observer/observer/event.dart';
2+
3+
class NewHashEvent extends Event {
4+
final String newHash;
5+
6+
NewHashEvent(this.newHash);
7+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import 'package:flutter/material.dart';
2+
import '../app_observer/observer/app_observer.dart';
3+
import 'widgets/hash_generator_widget.dart';
4+
import 'widgets/hash_user_widget.dart';
5+
6+
class SubscriberFlutterApp extends StatefulWidget {
7+
@override
8+
State<SubscriberFlutterApp> createState() => _SubscriberFlutterAppState();
9+
}
10+
11+
class _SubscriberFlutterAppState extends State<SubscriberFlutterApp> {
12+
final observer = AppObserver();
13+
14+
@override
15+
Widget build(BuildContext context) {
16+
return Scaffold(
17+
body: Center(
18+
child: Column(
19+
mainAxisAlignment: MainAxisAlignment.center,
20+
children: [
21+
HashUserWidget(observer: observer),
22+
HashGeneratorWidget(observer: observer),
23+
],
24+
),
25+
),
26+
);
27+
}
28+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import 'package:flutter/widgets.dart';
2+
3+
import '../../app_observer/observer/app_observer.dart';
4+
import '../../app_observer/observer/event.dart';
5+
6+
class SubscriberWidget<T extends Event> extends StatefulWidget {
7+
final AppObserver observer;
8+
final Widget Function(BuildContext buildContext, T? event) builder;
9+
10+
const SubscriberWidget({
11+
Key? key,
12+
required this.builder,
13+
required this.observer,
14+
}) : super(key: key);
15+
16+
@override
17+
State<SubscriberWidget<T>> createState() {
18+
return _SubscriberWidgetState<T>();
19+
}
20+
}
21+
22+
class _SubscriberWidgetState<T extends Event>
23+
extends State<SubscriberWidget<T>> {
24+
T? _event;
25+
26+
@override
27+
void initState() {
28+
widget.observer.subscribe<T>(update);
29+
super.initState();
30+
}
31+
32+
@override
33+
void dispose() {
34+
widget.observer.unsubscribe(update);
35+
super.dispose();
36+
}
37+
38+
void update(T event) {
39+
setState(() => _event = event);
40+
}
41+
42+
@override
43+
Widget build(BuildContext context) {
44+
return widget.builder(context, _event);
45+
}
46+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import 'dart:math';
2+
3+
import 'package:flutter/material.dart';
4+
5+
import '../../app_observer/observer/app_observer.dart';
6+
import '../events/new_hash_event.dart';
7+
8+
class HashGeneratorWidget extends StatelessWidget {
9+
final AppObserver observer;
10+
11+
const HashGeneratorWidget({
12+
Key? key,
13+
required this.observer,
14+
}) : super(key: key);
15+
16+
@override
17+
Widget build(BuildContext context) {
18+
return ElevatedButton(
19+
child: Text('Generate new hash'),
20+
onPressed: onHashGenerate,
21+
);
22+
}
23+
24+
void onHashGenerate() {
25+
final hash = Random().nextDouble().hashCode.toString();
26+
observer.notify(NewHashEvent(hash));
27+
}
28+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import 'package:flutter/widgets.dart';
2+
3+
import '../../app_observer/observer/app_observer.dart';
4+
import '../events/new_hash_event.dart';
5+
import '../subscriber/subscriber_widget.dart';
6+
7+
class HashUserWidget extends StatelessWidget {
8+
final AppObserver observer;
9+
10+
const HashUserWidget({Key? key, required this.observer}) : super(key: key);
11+
12+
@override
13+
Widget build(BuildContext context) {
14+
return SubscriberWidget<NewHashEvent>(
15+
observer: observer,
16+
builder: (context, event) {
17+
return Text(
18+
event?.newHash ?? 'Hash no generated',
19+
);
20+
},
21+
);
22+
}
23+
}

pubspec.yaml

Lines changed: 1 addition & 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.15.0
3+
version: 0.16.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

0 commit comments

Comments
 (0)