观察者模式(Publish/Subscribe),定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能自动更新自己。
C#观察者模式:
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中,我们可以使用委托与事件来简化观察者模式的实现,上面的例子用事件和委托的实现如下代码所示:
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);