using System;using System.Collections.Generic;using System.Threading;namespace RefactoringGuru.DesignPatterns.Observer.Conceptual
{publicinterfaceIObserver{// Receive update from subjectvoidUpdate(ISubject subject);}publicinterfaceISubject{// Attach an observer to the subject.voidAttach(IObserver observer);// Detach an observer from the subject.voidDetach(IObserver observer);// Notify all observers about an event.voidNotify();}// The Subject owns some important state and notifies observers when the// state changes.publicclassSubject:ISubject{// For the sake of simplicity, the Subject's state, essential to all// subscribers, is stored in this variable.publicint State {get;set;}=-0;// List of subscribers. In real life, the list of subscribers can be// stored more comprehensively (categorized by event type, etc.).private List<IObserver> _observers =newList<IObserver>();// The subscription management methods.publicvoidAttach(IObserver observer){
Console.WriteLine("Subject: Attached an observer.");this._observers.Add(observer);}publicvoidDetach(IObserver observer){this._observers.Remove(observer);
Console.WriteLine("Subject: Detached an observer.");}// Trigger an update in each subscriber.publicvoidNotify(){
Console.WriteLine("Subject: Notifying observers...");foreach(var observer in _observers){
observer.Update(this);}}// Usually, the subscription logic is only a fraction of what a Subject// can really do. Subjects commonly hold some important business logic,// that triggers a notification method whenever something important is// about to happen (or after it).publicvoidSomeBusinessLogic(){
Console.WriteLine("\nSubject: I'm doing something important.");this.State =newRandom().Next(0,10);
Thread.Sleep(15);
Console.WriteLine("Subject: My state has just changed to: "+this.State);this.Notify();}}// Concrete Observers react to the updates issued by the Subject they had// been attached to.classConcreteObserverA:IObserver{publicvoidUpdate(ISubject subject){if((subject as Subject).State <3){
Console.WriteLine("ConcreteObserverA: Reacted to the event.");}}}classConcreteObserverB:IObserver{publicvoidUpdate(ISubject subject){if((subject as Subject).State ==0||(subject as Subject).State >=2){
Console.WriteLine("ConcreteObserverB: Reacted to the event.");}}}classProgram{staticvoidMain(string[] args){// The client code.var subject =newSubject();var observerA =newConcreteObserverA();
subject.Attach(observerA);var observerB =newConcreteObserverB();
subject.Attach(observerB);
subject.SomeBusinessLogic();
subject.SomeBusinessLogic();
subject.Detach(observerB);
subject.SomeBusinessLogic();}}}