Skip to content

Latest commit

History

History

README.md

Observer Pattern

The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.

Problem

  • A one-to-many dependency between objects should be defined without making the objects tightly coupled.
  • It should be ensured that when one object changes state an open-ended number of dependent objects are updated automatically.
  • It should be possible that one object can notify an open-ended number of other objects.

Solution

  • Define Subject and Observer Objects
  • When a subject changes state, all registered observers are notified and updated automatically.

Common Structure

Observer Pattern

  • Subject (IObservable)

    • provides an interface for attaching and detaching Observer objects.
  • ConcreteSubject (WeatherData)

    • knows its observers.
    • sends a notification to its observers when its state changes
  • Observer (IObserver)

    • defines an updating interface for objects that should be notified of changes in a subject.
  • ConcreteObserver (CurrentConditionDisplay)

    • maintains a reference to a ConcreteSubject object
    • implements the Observer updating interface to keep its state consistent with the subject's.

    Collaboration

  • ConcreteSubject notifies its observers whenever a change occurs.

  • After being notified, a ConcreteObserver object may query the subject for information.

  • The Observer object that initiates the change request postpone its update until it gets a notification from the subject to avoid redundant updates.

  • Notify can be called by Subject, Observer or by any other object.

Benefits

  • Abstract coupling between Subject and Observer.
    • Subject is not coupled to concrete classes. All a subject knows is that it has a list of observers, each conforming to abstract Observer interface.
  • Observers can be attached and detached dynamically.
  • Support for broadcast communication
    • The subject doesn't care how many interested objects exist. The notification is broadcast automatically to all of them. It's up to the observer to handle or ignore a notification.

Drawbacks

  • Observers are notified in random order.
  • Unexpected updates
    • A seemingly innocuous operation on the subject may cause a cascade of updates to observers and their dependent objects.
    • If dependency criteria aren't well-defined or maintained, it can lead to spurious updates, which can be hard to track down.

Example

Definition

// Observable / SubjectpublicinterfaceIObservable<T>{voidaddObserver(IObserver<T>observer);voidremoveObserver(IObserver<T>observer);voidnotifyObservers();}// ObserverpublicinterfaceIObserver<T>{voidUpdate(Tdata);}

Observer Pattern

Usage

WeatherDatadata=newWeatherData(13);CurrentConditionDisplaydisplay1=newCurrentConditionDisplay("Display1",data);// OUTPUT --> Display1 - Temperature: 13CurrentConditionDisplaydisplay2=newCurrentConditionDisplay("Display2",data);// OUTPUT --> Display2 - Temperature: 13// update the temperature.data.Temperature=14;// Display 1 and 2 show the new temperature// OUTPUT: /* Weather data is updated Display1 - Temperature: 14 Weather data is updated Display2 - Temperature: 14 */data.removeObserver(display2);data.Temperature=15;// Only Display 1 shows the new temperature// OUTPUT: /* Weather data is updated Display1 - Temperature: 15 */Console.ReadLine();

Checkout built-it Observer Pattern in .NET - Observer Design Pattern Best Practices

.NET Event

Define update method as a delegate.

publicdelegatevoidTemperatureChanged(WeatherDataWithEventweatherData);

ConcreateSubject/Observable creates an event with the defined delegate method above.

publicclassWeatherDataWithEvent{privatefloattemperature;// declare event OnTemperatureChangedpubliceventTemperatureChangedOnTemperatureChanged;publicfloatTemperature{get{returnthis.temperature;}set{this.temperature=value;// event subscribers will be notifiedOnTemperatureChanged?.Invoke(this);}}}
```
Observerscan register themselves as follows
```cs
// Class: CurrentConditionDisplayWithEvent// subscribeweatherData.OnTemperatureChanged +=this.OnTemperatureChanged;// unsubscribeweatherData.OnTemperatureChanged-=this.OnTemperatureChanged;

Relations with Other Patterns

  • Mediator - By encapsulating complex update semantics, the ChangeManager acts as mediator between subjects and observers.
  • Singleton: The ChangeManager may use the Singleton pattern to make it unique and globally accessible.