Star Wars Meets Software Development: A Guide to Implementing the Observer Pattern in C#
Luke: Master Yoda, I need guidance
![](https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F79ec0d29-7cba-40a2-a7ec-4d392ba7140b_2775x1567.png)
Yoda: Yes, young Luke
![](https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F18048a7c-64b5-41ca-b681-951b3e0a3317_2782x1575.png)
Luke: "Master Yoda, I am having trouble communicating with the other Jedi in the council. We are all working on different missions, and I do not know what is happening with them."
![](https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086c27a8-89e6-4181-b798-4fb99f236674_2788x1563.png)
Yoda: "Ah, young Padawan, you are experiencing a problem with coordination and communication. In programming, this is a common problem that can be addressed with the Observer pattern.
![](https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdf8a81a2-c0a1-4442-ba74-c8b90c033dcc_2776x1544.png)
Yoda: For example, we can use this pattern to keep track of the status of Jedi missions. Let's say that you have a JediCouncil class, which contains a list of Jedi Knights who are undertaking different missions. Each of these Jedi Knights has a MissionStatus property that indicates whether the mission is ongoing, completed, or failed.
![](https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc40921c3-9b94-4476-b5d5-9a32a6da2609_2768x1562.png)
Yoda: In C#, we can implement the Observer pattern by having the JediCouncil class implement the IObservable interface, and each JediKnight class implement the IObserver interface.
![](https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4895609-c8ca-4bd2-94ef-a706e1629a55_2781x1569.png)
public class JediCouncil : IObservable<JediKnight>
{
private List<JediKnight> _jediKnights;
private List<IObserver<JediKnight>> _observers;
public JediCouncil()
{
_jediKnights = new List<JediKnight>();
_observers = new List<IObserver<JediKnight>>();
}
public void AddJediKnight(JediKnight jediKnight)
{
_jediKnights.Add(jediKnight);
NotifyObservers(jediKnight);
}
public void RemoveJediKnight(JediKnight jediKnight)
{
_jediKnights.Remove(jediKnight);
}
public IDisposable Subscribe(IObserver<JediKnight> observer)
{
_observers.Add(observer);
return new Unsubscriber(_observers, observer);
}
private void NotifyObservers(JediKnight jediKnight)
{
foreach (var observer in _observers)
{
observer.OnNext(jediKnight);
}
}
private class Unsubscriber : IDisposable
{
private List<IObserver<JediKnight>> _observers;
private IObserver<JediKnight> _observer;
public Unsubscriber(List<IObserver<JediKnight>> observers, IObserver<JediKnight> observer)
{
_observers = observers;
_observer = observer;
}
public void Dispose()
{
if (_observer != null && _observers.Contains(_observer))
{
_observers.Remove(_observer);
}
}
}
}
using System;
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
var jediCouncil = new JediCouncil();
var Luke = new JediKnight {Name = "Luke Skywalker", Status = MissionStatus.Ongoing};
var Leia = new JediKnight {Name = "Leia Organa", Status = MissionStatus.Ongoing};
var Han = new JediKnight {Name = "Han Solo", Status = MissionStatus.Ongoing};
jediCouncil.AddJediKnight(Luke);
jediCouncil.AddJediKnight(Leia);
jediCouncil.AddJediKnight(Han);
var observer1 = jediCouncil.Subscribe(new JediCouncilObserver());
//Change the mission status of Luke, triggers the OnNext on the observer
Luke.Status = MissionStatus.Completed;
//Change the mission status of Leia, triggers the OnNext on the observer
Leia.Status = MissionStatus.Failed;
//Unsubscribe observer1
observer1.Dispose();
//Change the mission status of Han, it will not trigger OnNext, observer1 is unsubscribed
Han.Status = MissionStatus.Completed;
}
}
public class JediKnight : IObserver<JediKnight>
{
public string Name { get; set; }
public MissionStatus Status { get; set; }
public void OnCompleted()
{
// Notify the observer that all updates have been received
}
public void OnError(Exception error)
{
// Notify the observer of an error
}
public void OnNext(JediKnight jediKnight)
{
// Update the status of the Jedi Knight
}
}
![](https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F801344b1-496e-45c5-bbfe-bce3918a1ff3_2770x1559.png)
![](https://substackcdn.com/image/fetch/w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84332e03-1c39-4fc2-805d-fbb859070dfb_2778x1562.png)
Other design pattern articles:
Decorator Pattern: https://zahere.com/yoda-and-the-decorator-pattern-a-lesson-for-luke
Strategy and Factory Pattern: https://zahere.com/opinion-strategy-pattern-factory-pattern-will-be-the-most-used-design-pattern-in-your-career
If you liked my content, do kindly like and share in your network. And don't forget to subscribe to the newsletter to NEVER miss an article.