Objective 🎯
Define a one-to-many dependency between objects in a way that when one object changes its state or any specific attribute, all its dependents (a.k.a. observers) will be notified automatically.
Type ✅
✔️Behavioral: Describes how objects interact/communicate between themselves.
❌Creational: Describes how to instantiate an object without large and complex.
❌Structural: Describes how objects/classes are composed to form larger structures.
UML 📐
Participants 🔗
• Subject:
- Holds a list of observers
- Provides an interface for attaching/detaching Observer objects
• ConcreteSubject:
- Sends a notification to its observers when its state/properties change
• Observer:
- Defines an interface to allow objects to be notified when the subject changes
• ConcreteObserver:
- Maintains a reference to a ConcreteSubject object
- Stores an internal state that should be consistent with the Subject’s state (if needed)
- Implements the Observer updating interface to keep its state in sync with the Subject’s
Sample Code 🎮
Structural Example 🏛️
public static class ObserverStructural
{
public static void Execute()
{
ConcreteSubject lConcreteSubject = new ConcreteSubject();
lConcreteSubject.Attach(new ConcreteObserver1(lConcreteSubject));
lConcreteSubject.Attach(new ConcreteObserver2(lConcreteSubject));
lConcreteSubject.SubjectState = "State2";
lConcreteSubject.SubjectState = "State3";
}
}
public abstract class Subject
{
private List<Observer> _Observers = new List<Observer>();
public void Attach(Observer prObserver)
{
_Observers.Add(prObserver);
}
public void Detach(Observer prObserver)
{
_Observers.Remove(prObserver);
}
protected void NotifyObservers()
{
foreach (Observer lObserverCurrent in _Observers)
{
lObserverCurrent.Update();
}
}
}
public abstract class Observer
{
public ConcreteSubject _ConcreteSubject;
public string _Name { get; set; }
public string _ObserverState { get; set; }
public Observer(ConcreteSubject prConcreteSubject)
{
_ConcreteSubject = prConcreteSubject;
}
public abstract void Update();
}
public class ConcreteObserver1 : Observer
{
public ConcreteObserver1(ConcreteSubject prConcreteSubject) : base(prConcreteSubject) { }
public override void Update()
{
Console.WriteLine("Concrete Observer 1 Triggered");
}
}
public class ConcreteObserver2 : Observer
{
public ConcreteObserver2(ConcreteSubject prConcreteSubject) : base(prConcreteSubject) { }
public override void Update()
{
Console.WriteLine("Concrete Observer 2 Triggered");
}
}
public class ConcreteSubject : Subject
{
private string _SubjectState = "State1";
public string SubjectState
{
get { return _SubjectState; }
set
{
Console.WriteLine($"Changing Subject's State from {_SubjectState} to {value}");
_SubjectState = value;
NotifyObservers();
}
}
}
Output
Real-world Example 🔥
public static class ObserverPractical
{
public static void Execute()
{
JohnPoliticalFigure lJohnPoliticalFigure = new JohnPoliticalFigure();
lJohnPoliticalFigure.Attach(new Mike());
lJohnPoliticalFigure.Attach(new Harry());
lJohnPoliticalFigure.NewTweet("Lorem ipsum dolor sit amet, consectetur adipiscing");
lJohnPoliticalFigure.NewTweet("Mauris vitae orci a dolor bibendum gravida");
}
}
public abstract class TwitterProfile
{
private List<TwitterFollower> _Followers = new List<TwitterFollower>();
public void Attach(TwitterFollower prFollower)
{
_Followers.Add(prFollower);
}
public void Detach(TwitterFollower prFollower)
{
_Followers.Remove(prFollower);
}
protected void NotifyFollowers(string prTweet)
{
foreach (TwitterFollower lFollowerCurrent in _Followers)
{
lFollowerCurrent.NotifyNewTweet(prTweet);
}
}
}
public abstract class TwitterFollower
{
public abstract void NotifyNewTweet(string prTweet);
}
public class Mike : TwitterFollower
{
public override void NotifyNewTweet(string prTweet)
{
Console.WriteLine($"Notifying User \"Mike\"");
}
}
public class Harry : TwitterFollower
{
public override void NotifyNewTweet(string prTweet)
{
Console.WriteLine($"Notifying User \"Harry\"");
}
}
public class JohnPoliticalFigure : TwitterProfile
{
public void NewTweet(string prTweet)
{
Console.WriteLine("New Tweet from John: " + prTweet);
NotifyFollowers(prTweet);
}
}
Output