/* My example of the observer pattern This program is based on the observer pattern "real world" example on the d&o factory patterns website. I wrote it intially to teach myself the pattern. Compile with: csc observer.cs invest.cs */ using System; using System.Collections; //// compile with observer.cs class stock : observee { public readonly string symbol; public double price; // probably should be private, but nah ... public double oldprice; // keeps track of changes in price public stock(string s, double p) { symbol=s; price=p; } // constructor public void changeprice(double amt) // +amt for gain, -amt for loss { oldprice = price; price += amt; notify(); // notify investors } ///////// implementation of observee interface ArrayList investors = new ArrayList(); public void attach(observer obv) { investors.Add(obv); } public void detach(observer obv) { investors.Remove(obv); } public void notify() { foreach (object x in investors) { ((observer)x).update(this); } } public void notify(observer obv) { obv.update(this); } } // class stock class investor : observer // basic investor superclass { public void invest(stock s) { s.attach(this); } public void sellAll(stock s) { s.detach(this); // presumably there will be other data structures to keep track // of how many shares the investor own, etc..., but we'll keep it // simple here. the purpose is to demonstrate the observer pattern. } public virtual object update(observee obe) // to be overridden { return null; } } // class investor //////////// concrete investors AND observers class bullinvestor : investor, observer // a bull buys when stocks fall { public override object update(observee obe) { stock s = (stock)obe; // need to typecast before using obe as a stock if (s.price <= s.oldprice) Console.WriteLine(" buy buy buy! "); return null; } } class bearinvestor : investor, observer // a bear buys when stocks rise { public override object update(observee obe) { stock s = (stock)obe; if (s.price > s.oldprice) Console.WriteLine(" buy. "); else Console.WriteLine(" sell sell sell! "); return null; } } ///////////////// public class invest { public static void Main() { stock intel = new stock("INTC",20); stock microsoft = new stock("MSFT",40); stock nvidia = new stock("NVDA",10); investor me = new bearinvestor(); investor you = new bullinvestor(); me.invest(intel); me.invest(nvidia); you.invest(intel); you.invest(microsoft); intel.changeprice(+1.5); microsoft.changeprice(-0.5); nvidia.changeprice(-1.0); } // main } /* The benefit of the observer pattern is the way that main can now be written. There is on need to maintain any external data structures to keep track of the investments, and no need to have zillions of if-elses to determine the correct behavior of each investor or stock. This program is close to being "fully object oriented". The OOP principle to "let objects decide what to do themselves" is realized. */