# Star Wars Meets Software Development: A Guide to Implementing the Observer Pattern in C#

Luke: Master Yoda, I need guidance

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673421382672/0c5211d0-2148-4c5a-92e7-2442f09eb73a.png align="center")

Yoda: Yes, young Luke

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673421401975/92dc70ad-d689-4250-9b37-26d4cfd9a2f4.png align="center")

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://cdn.hashnode.com/res/hashnode/image/upload/v1673421423459/df1b21e3-bcd4-44ce-9e13-3ceb7f010655.png align="center")

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://cdn.hashnode.com/res/hashnode/image/upload/v1673421449958/952a1345-b83f-41a7-854a-3416e23bbf22.png align="center")

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://cdn.hashnode.com/res/hashnode/image/upload/v1673421475562/39852dea-1100-4bf5-ae9f-bed7dd82f332.png align="center")

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://cdn.hashnode.com/res/hashnode/image/upload/v1673421740991/40abcf22-3066-414c-8d51-95bcd6a78e8b.png align="center")

```csharp
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);
            }
        }
    }
}
```

```csharp
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;
    }
}
```

```csharp
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://cdn.hashnode.com/res/hashnode/image/upload/v1673422652109/9b59eba8-9d9c-4ffb-842f-4df6cc4fe512.png align="center")

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1673422668819/0e8b8f92-27c4-4d54-9dc7-5888f64a6799.png align="center")

Other design pattern articles:

Decorator Pattern: [https://zahere.com/yoda-and-the-decorator-pattern-a-lesson-for-luke](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](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.
