The Observer Pattern: Simple Approach to Reactivity
The Observer pattern is one of the fundamental pillars of object-oriented programming. It allows an object, called a “observable”, notify other objects, the “observers”, about any change in their own state. This notification allows observers to react and update their status.
Basically, an observer subscribes to observe changes in an observable and is notified whenever that change occurs.
Advantages of the Observer Standard:
- Decoupling: Observers are decoupled from the observable, allowing changes in the observable without directly affecting the observers.
- Ease of Scale: New observers can be added easily by extending the functionality without modifying the observable.
- Reactivity: Observers are instantly notified of changes, enabling real-time reactions.
When to Use the Observer Pattern?
The Observer pattern is useful in situations where changes to one object/variable need to be reflected in other objects without creating direct dependencies between them. It is ideal when you want to automatically update multiple user interface elements, notify events, or spread state changes
Flutter/Dart Implementation Example:
In Flutter, we can use the Observer pattern to update the user interface when the state of an object changes. There goes a to-do list application, which can be quickly tested on the DartPad
// Definition of Observable
class TasksList {
List<String> _tasks = [];
List<Function> _observers = [];
void addTask(String newTask) {
_tasks.add(newTask);
notifyObservers();
}
void registerObserver(Function observer) {
_observers.add(observer);
}
void notifyObservers() {
for (var observer in _observers) {
observer();
}
}
}
As we have seen before, there are two components to act, in this first excerpt above we define the Observable component
let us now look at the Observer
// Implementation of the Observer
class InterfaceUser {
ListTasks list;
UserInterface(this.list) {
list.registerObserver(update);
}
void update() {
// Updates the interface according to changes in the task list
print("Updated task list: ${list._tasks}");
}
}
This way we go for use:
void main() {
Tasks List = TasksList();
InterfaceUser interfaceUser = InterfaceUser(list);
list.addTask("Task No 1");
}
In this example, the class TaskList it is the observable and the class InterfaceUser it's observer. When a new task is added to the list, the user interface is automatically updated through the method update()
.
and for those who already code with flutter, you should remember packages like Provider or even the native ChangeNotifier , which uses this technique for state management of applications.