觀察者模式: ide
1、定義:this
觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知全部觀察者對象,使它們可以自動更新本身。此種模式一般被用來實時事件處理系統。其中兩個重要對象是觀察者和主題,要想主題對象發生改變時,能通知到全部觀察者角色,則天然主題角色必須引用觀察者,從而完成觀察模式。spa
特色:code
一、定義了一對多的關係。server
二、主題用一個共同的接口來更新觀察者。對象
三、觀察者和主題用鬆耦合的方式結合,不須要知道實現細節,只須要實現接口就能夠。blog
2、UML類圖:接口
3、基本代碼: 事件
class Program { static void Main(string[] args) { ConcreteSubject cs = new ConcreteSubject(); cs.Attach(new ConcreteObserver(cs, "x")); cs.Attach(new ConcreteObserver(cs, "y")); cs.SubjectState = "abc"; cs.Notify(); Console.Read(); } } abstract class Subject { private IList<Observer> observers = new List<Observer>(); public void Attach(Observer observer) { observers.Add(observer); } public void Detach(Observer observer) { observers.Remove(observer); } public void Notify() { foreach (Observer ob in observers) { ob.Update(); } } } class ConcreteSubject : Subject { private string subjectState; public string SubjectState { get { return subjectState; } set { subjectState = value; } } } abstract class Observer { public abstract void Update(); } class ConcreteObserver : Observer { private string name; private string observerState; private ConcreteSubject subject; public ConcreteSubject Subject { get { return subject; } set { subject = value; } } public ConcreteObserver(ConcreteSubject subject, string name) { this.subject = subject; this.name = name; } public override void Update() { observerState = subject.SubjectState; Console.WriteLine("觀察者{0}的新狀態是{1}", name, observerState); } }
4、適用場景:get
當一個對象的改變須要同時改變其餘對象時,並且不知道具體有多少對象有待改變時,應該考慮使用觀察者模式。
舉例說明:
實例代碼:
interface ISubject { void Attach(Observer observer); void Detach(Observer observer); void Notify(); string SubjectState { get; set; } } class Boss : ISubject { private IList<Observer> observers = new List<Observer>(); private string bossAction; public string SubjectState { get { return bossAction; } set { bossAction = value; } } public void Attach(Observer observer) { observers.Add(observer); } public void Detach(Observer observer) { observers.Remove(observer); } public void Notify() { foreach (Observer ob in observers) { ob.Update(); } } } abstract class Observer { protected string name; protected ISubject subject; public Observer(string name, ISubject subject) { this.name = name; this.subject = subject; } public abstract void Update(); } class StockObserver : Observer { public StockObserver (string name,ISubject subject):base(name,subject ) {} public override void Update() { Console.WriteLine("{0},{1} 關閉股票,繼續工做", subject.SubjectState, name); } } class NBAObserver : Observer { public NBAObserver (string name,ISubject subject):base(name,subject) {} public override void Update() { Console.WriteLine("{0},{1} 關閉NBA,繼續工做", subject.SubjectState, name); } }
Boss boss = new Boss(); Observer s1 = new StockObserver("張三", boss); Observer s2 = new NBAObserver("李四", boss); boss.Attach(s1); boss.Attach(s2); boss.SubjectState = "老闆回來了"; boss.Notify();
5、觀察者模式的缺點及解決方法:
在具體前臺、同事和老闆的實例中,使用依賴倒轉原則,可是「抽象通知者」仍是依賴「抽象觀察者」,即若是沒有抽象觀察者這樣的接口,通知功能就完不成。另外就是每一個具體觀察者,它不必定是「更新」的方法要調用,多是其餘的方法。解決方法:通知者和觀察者之間根本互相不知道,由客戶端決定通知誰。對於前臺的實例,決定使用委託的方式來實現由客戶端來決定具體通知誰的功能。
實例說明:
interface ISubject { void Notify(); string SubjectState { get; set; } } public delegate void DelegateHandler(); class Boss : ISubject { public event DelegateHandler Update; public string SubjectState { get; set; } public void Notify() { Update(); } } abstract class Observer { protected string name; protected ISubject subject; public Observer(string name, ISubject subject) { this.name = name; this.subject = subject; } public abstract void Update(); } class StockObserver : Observer { public StockObserver(string name, ISubject subject) : base(name, subject) { } public override void Update() { Console.WriteLine("{0},{1} 關閉股票,繼續工做", subject.SubjectState, name); } } class NBAObserver : Observer { public NBAObserver(string name, ISubject subject) : base(name, subject) { } public override void Update() { Console.WriteLine("{0},{1} 關閉NBA,繼續工做", subject.SubjectState, name); } }
Boss boss = new Boss(); StockObserver s1 = new StockObserver("張三", boss); NBAObserver s2 = new NBAObserver("李四", boss); boss.Update += new DelegateHandler(s1.Update); boss.Update += new DelegateHandler(s2.Update); boss.SubjectState = "老闆回來了"; boss.Notify();
6、總結:
觀察者模式所作的工做其實就是在解除耦合。讓耦合的雙方都依賴於抽象,而不是依賴於具體,從而使各自的變化都不會影響到另外一邊的變化。