觀察者模式(Publish/Subscribe),定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知全部觀察者對象,使它們能自動更新本身。緩存
C#觀察者模式:app
namespace 觀察者模式 { class Program { static void Main(string[] args) { //老闆胡漢三 Boss huhansan = new Boss(); //看股票的同事 StockObserver tongshi1 = new StockObserver("魏關奼", huhansan); //看NBA的同事 NBAObserver tongshi2 = new NBAObserver("易管查", huhansan); huhansan.Attach(tongshi1); huhansan.Attach(tongshi2); huhansan.Detach(tongshi1); //老闆回來 huhansan.SubjectState = "我胡漢三回來了!"; //發出通知 huhansan.Notify(); Console.Read(); } } //通知者接口 interface Subject { void Attach(Observer observer); void Detach(Observer observer); void Notify(); string SubjectState { get; set; } } class Secretary : Subject { //同事列表 private IList<Observer> observers = new List<Observer>(); private string action; //增長 public void Attach(Observer observer) { observers.Add(observer); } //減小 public void Detach(Observer observer) { observers.Remove(observer); } //通知 public void Notify() { foreach (Observer o in observers) o.Update(); } //前臺狀態 public string SubjectState { get { return action; } set { action = value; } } } class Boss : Subject { //同事列表 private IList<Observer> observers = new List<Observer>(); private string action; //增長 public void Attach(Observer observer) { observers.Add(observer); } //減小 public void Detach(Observer observer) { observers.Remove(observer); } //通知 public void Notify() { foreach (Observer o in observers) o.Update(); } //老闆狀態 public string SubjectState { get { return action; } set { action = value; } } } //抽象觀察者 abstract class Observer { protected string name; protected Subject sub; public Observer(string name, Subject sub) { this.name = name; this.sub = sub; } public abstract void Update(); } //看股票的同事 class StockObserver : Observer { public StockObserver(string name, Subject sub) : base(name, sub) { } public override void Update() { Console.WriteLine("{0} {1} 關閉股票行情,繼續工做!", sub.SubjectState, name); } } //看NBA的同事 class NBAObserver : Observer { public NBAObserver(string name, Subject sub) : base(name, sub) { } public override void Update() { Console.WriteLine("{0} {1} 關閉NBA直播,繼續工做!", sub.SubjectState, name); } } }
在.NET中,咱們能夠使用委託與事件來簡化觀察者模式的實現,上面的例子用事件和委託的實現以下代碼所示:ide
namespace 觀察者模式_委託 { class Program { static void Main(string[] args) { //老闆胡漢三 Boss huhansan = new Boss(); //看股票的同事 StockObserver tongshi1 = new StockObserver("魏關奼", huhansan); //看NBA的同事 NBAObserver tongshi2 = new NBAObserver("易管查", huhansan); huhansan.Update += new EventHandler(tongshi1.CloseStockMarket); huhansan.Update += new EventHandler(tongshi2.CloseNBADirectSeeding); //老闆回來 huhansan.SubjectState = "我胡漢三回來了!"; //發出通知 huhansan.Notify(); Console.Read(); } } //通知者接口 interface Subject { void Notify(); string SubjectState { get; set; } } //事件處理程序的委託 delegate void EventHandler(); class Secretary : Subject { //聲明一事件Update,類型爲委託EventHandler public event EventHandler Update; private string action; public void Notify() { Update(); } public string SubjectState { get { return action; } set { action = value; } } } class Boss : Subject { //聲明一事件Update,類型爲委託EventHandler public event EventHandler Update; private string action; public void Notify() { Update(); } public string SubjectState { get { return action; } set { action = value; } } } //看股票的同事 class StockObserver { private string name; private Subject sub; public StockObserver(string name, Subject sub) { this.name = name; this.sub = sub; } //關閉股票行情 public void CloseStockMarket() { Console.WriteLine("{0} {1} 關閉股票行情,繼續工做!", sub.SubjectState, name); } } //看NBA的同事 class NBAObserver { private string name; private Subject sub; public NBAObserver(string name, Subject sub) { this.name = name; this.sub = sub; } //關閉NBA直播 public void CloseNBADirectSeeding() { Console.WriteLine("{0} {1} 關閉NBA直播,繼續工做!", sub.SubjectState, name); } } }
js觀察者模式:函數
var event = { clientList:[], listen:function(key,fn){ if(!this.clientList[key]){ this.clientList[key] = []; } this.clientList[key].push(fn); //訂閱的消息加進緩存列表 }, trigger:function(){ var key = Array.prototype.shift.call(arguments), fns = this.clientList[key]; if(!fns || fns.length === 0){ //若是沒有綁定對應的消息 return false; } for(var i =0, fn; fn=fns[i++];){ fn.apply(this,arguments); } }, remove:function(key,fn){ var fns = this.clientList[key]; if(!fns){ //若是key對應的消息沒有被人訂閱,則直接返回 return false; } if(!fn){ //若是沒有傳入具體的回調函數,表示須要取消key對應的全部訂閱 fns && (fns.length = 0); }else{ for(var i=fns.length - 1; i>=0;i--){ var _fn = fns[i]; if(_fn === fn){ fns.splice(i,1); //刪除訂閱者的回調函數 } } } } }; //調用: var salesOffices = {}; $.extend(salesOffices,event); salesOffices.listen('squareMeter',function(price){ alert('價格=' + price); }); salesOffices.trigger('squareMeter',20000); //全局調用: event.listen('squareMeter',function(price){ alert('價格=' + price); }); event.trigger('squareMeter',20000);