using System; namespaceObserverPatternDemo { publicinterfaceIObserver { // Receive update from subject voidUpdate(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.). 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... } } }