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.). privateList<IObserver> _observers = new List<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 = new Random().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 = new Subject(); var observerA = new ConcreteObserverA(); subject.Attach(observerA);
var observerB = new ConcreteObserverB(); subject.Attach(observerB);
Subject: Attached an observer. Subject: Attached an observer.
Subject: I'm doing something important. Subject: My state has just changed to: 2 Subject: Notifying observers... ConcreteObserverA: Reacted to the event. ConcreteObserverB: Reacted to the event.
Subject: I'm doing something important. Subject: My state has just changed to: 1 Subject: Notifying observers... ConcreteObserverA: Reacted to the event. Subject: Detached an observer.
Subject: I'm doing something important. Subject: My state has just changed to: 5 Subject: Notifying observers...