|
| 1 | +<h1> Easy Example </h1> |
| 2 | + |
| 3 | +- src: https://refactoring.guru/design-patterns/observer/csharp/example |
| 4 | + |
| 5 | +- Observer is a behavioral design pattern |
| 6 | + - that allows some objects to notify other objects about changes in their state. |
| 7 | +- The Observer pattern provides a way to subscribe and unsubscribe to and from these events for any object that implements a subscriber interface. |
| 8 | + |
| 9 | +--- |
| 10 | + |
| 11 | +- Usage examples: |
| 12 | +- especially in the GUI components. |
| 13 | +- It provides a way to react to events happening in other objects without coupling to their classes. |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +- Identification: |
| 18 | +- The pattern can be recognized if you see a subscription method that stores incoming objects in a list. |
| 19 | +- You can confirm the identification, |
| 20 | +- if you see some sort of notification method that iterates over objects in that list and calls their “update” method. |
| 21 | + |
| 22 | +```dart |
| 23 | +abstract class BaseObserver { |
| 24 | + /// Receive update from subject |
| 25 | + void Update(BaseSubject subject); |
| 26 | +} |
| 27 | +``` |
| 28 | + |
| 29 | +```dart |
| 30 | +abstract class BaseSubject { |
| 31 | + // Attach an observer to the subject. |
| 32 | + void Attach(BaseObserver observer); |
| 33 | +
|
| 34 | + // Detach an observer from the subject. |
| 35 | + void Detach(BaseObserver observer); |
| 36 | +
|
| 37 | + // Notify all observers about an event. |
| 38 | + void Notify(); |
| 39 | +} |
| 40 | +``` |
| 41 | + |
| 42 | +```dart |
| 43 | +// The Subject owns some important state and notifies observers when the |
| 44 | +// state changes. |
| 45 | +class Subject implements BaseSubject { |
| 46 | + // For the sake of simplicity, the Subject's state, essential to all |
| 47 | + // subscribers, is stored in this variable. |
| 48 | + int state = 0; |
| 49 | +
|
| 50 | + // List of subscribers. In real life, the list of subscribers can be |
| 51 | + // stored more comprehensively (categorized by event type, etc.). |
| 52 | + List<BaseObserver> _observers = []; |
| 53 | +
|
| 54 | + // The subscription management methods. |
| 55 | + void Attach(BaseObserver observer) { |
| 56 | + print("Subject: Attached an observer."); |
| 57 | + _observers.add(observer); |
| 58 | + } |
| 59 | +
|
| 60 | + void Detach(BaseObserver observer) { |
| 61 | + _observers.remove(observer); |
| 62 | + print("Subject: Detached an observer."); |
| 63 | + } |
| 64 | +
|
| 65 | + // Trigger an update in each subscriber. |
| 66 | + void Notify() { |
| 67 | + print("Subject: Notifying observers..."); |
| 68 | +
|
| 69 | + for (var observer in _observers) { |
| 70 | + observer.Update(this); |
| 71 | + } |
| 72 | + } |
| 73 | +
|
| 74 | + // Usually, the subscription logic is only a fraction of what a Subject |
| 75 | + // can really do. Subjects commonly hold some important business logic, |
| 76 | + // that triggers a notification method whenever something important is |
| 77 | + // about to happen (or after it). |
| 78 | + void SomeBusinessLogic() { |
| 79 | + print("\nSubject: I'm doing something important."); |
| 80 | + state = new math.Random().nextInt(10); |
| 81 | +
|
| 82 | + print("Subject: My state has just changed to: $state"); |
| 83 | + Notify(); |
| 84 | + } |
| 85 | +} |
| 86 | +``` |
| 87 | + |
| 88 | +```dart |
| 89 | +// Concrete Observers react to the updates issued by the Subject they had |
| 90 | +// been attached to. |
| 91 | +class ConcreteObserverA implements BaseObserver { |
| 92 | + void Update(BaseSubject subject) { |
| 93 | + if (subject is Subject) { |
| 94 | + if (subject.state < 3) { |
| 95 | + print("subject is Subject :: (subject.state < 3)"); |
| 96 | + } |
| 97 | + } |
| 98 | + print("Not Subject OR Not (subject.state < 3)"); |
| 99 | + } |
| 100 | +} |
| 101 | +
|
| 102 | +class ConcreteObserverB implements BaseObserver { |
| 103 | + void Update(BaseSubject subject) { |
| 104 | + if (subject is Subject) { |
| 105 | + print("ConcreteObserverB: Reacted to the event."); |
| 106 | + } |
| 107 | + } |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +```dart |
| 112 | +void main() { |
| 113 | + // The client code. |
| 114 | + var subject = new Subject(); |
| 115 | + var observerA = new ConcreteObserverA(); |
| 116 | + subject.Attach(observerA); |
| 117 | +
|
| 118 | + var observerB = new ConcreteObserverB(); |
| 119 | + subject.Attach(observerB); |
| 120 | +
|
| 121 | + subject.SomeBusinessLogic(); |
| 122 | + subject.SomeBusinessLogic(); |
| 123 | +
|
| 124 | + subject.Detach(observerB); |
| 125 | +
|
| 126 | + subject.SomeBusinessLogic(); |
| 127 | +} |
| 128 | +
|
| 129 | +``` |
| 130 | + |
| 131 | +```dart |
| 132 | +// Output.txt: Execution result |
| 133 | +// Subject: Attached an observer. |
| 134 | +// Subject: Attached an observer. |
| 135 | +
|
| 136 | +// Subject: I'm doing something important. |
| 137 | +// Subject: My state has just changed to: 2 |
| 138 | +// Subject: Notifying observers... |
| 139 | +// ConcreteObserverA: Reacted to the event. |
| 140 | +// ConcreteObserverB: Reacted to the event. |
| 141 | +
|
| 142 | +// Subject: I'm doing something important. |
| 143 | +// Subject: My state has just changed to: 1 |
| 144 | +// Subject: Notifying observers... |
| 145 | +// ConcreteObserverA: Reacted to the event. |
| 146 | +// Subject: Detached an observer. |
| 147 | +
|
| 148 | +// Subject: I'm doing something important. |
| 149 | +// Subject: My state has just changed to: 5 |
| 150 | +// Subject: Notifying observers... |
| 151 | +``` |
0 commit comments