慢慢的做記錄,做最強大的自己 看了大話設計模式之後感觸很深,發現自己還有很多學習的東西,設計軟體並不是一兩句代碼把功能寫完了就行,需要思考的內容有很多 代碼來源參考大話設計模式這本書,這裡在博客里記錄一下,不可能每次都去翻書,但是在博客裡面是非常好找的。 觀察者模式(Observer)算是設計模式里 ...
慢慢的做記錄,做最強大的自己
看了大話設計模式之後感觸很深,發現自己還有很多學習的東西,設計軟體並不是一兩句代碼把功能寫完了就行,需要思考的內容有很多
代碼來源參考大話設計模式這本書,這裡在博客里記錄一下,不可能每次都去翻書,但是在博客裡面是非常好找的。
觀察者模式(Observer)算是設計模式裡面最經典的一個模式了,這個模式可以應用在業務邏輯處理與界面交互的過程中,官方解釋就是在此種模式中,
一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統。
舉一個簡單的例子,之前看到的面試題:
貓看見很多老鼠在偷米吃,大叫了一聲,主人醒了,這就是一個經典的觀察者模式,老鼠跟主人都是觀察者(Observer),而貓是一個被觀察者(Subject)
之前我同事還給我舉了一個例子:項目經理,前臺妹紙,還有科室成員,怎麼防止項目經理突然間在同事都在做非工作上的事情時,提前預知,那麼就需要前臺妹紙去觀察了。
那麼怎麼去實現觀察者模式呢,那就是把觀察者當一個整體給抽象出來。
就以貓遇見老鼠叫主人被驚醒這個為例子:
首先,理解一下觀察者是誰,這裡面誰跟誰是什麼關係,老鼠遇見貓又是什麼反應,貓叫聲對主人又產生了什麼影響
public interface Observer { void Response(); //觀察者的響應,如是老鼠見到貓的反映 } public interface Subject { void AimAt(Observer obs); //針對哪些觀察者,這裡指貓的要撲捉的對象---老鼠,還有貓驚醒的主人 }
老鼠見到貓的反應用一個類寫出來
public class Mouse : Observer { private string name; public Mouse(string name, Subject subj) { this.name = name; subj.AimAt(this); } public void Response() { Console.WriteLine(name + " 開始逃竄!"); } }
然後主人被貓叫聲吵醒,也是一個反應,這裡繼承觀察者
public class Master : Observer { public Master(Subject subj) { subj.AimAt(this); } public void Response() { Console.WriteLine("吵死了!"); } }
貓是被觀察者,主要產生的行為就是大叫一聲
public class Cat : Subject { private ArrayList observers; public Cat() { this.observers = new ArrayList(); } public void AimAt(Observer obs) { this.observers.Add(obs); } public void Cry() { Console.WriteLine("貓大叫一聲!"); foreach (Observer obs in this.observers) { obs.Response(); } } }
整個過程在客戶端的代碼就是這樣的
class MainClass { static void Main(string[] args) { Cat cat = new Cat(); Mouse mouse1 = new Mouse("mouse1", cat); Mouse mouse2 = new Mouse("mouse2", cat); Master master = new Master(cat); cat.Cry(); } }
當然這裡耦合程度還是很高,主人跟老鼠的行為都是高度依賴貓這個抽象的觀察者,怎麼改才能解耦,那麼就需要用到另外一種方式:事件委托
這裡聲明瞭一個委托事件
public delegate void SubEventHandler(); public abstract class Subject { public event SubEventHandler SubEvent; protected void FireAway() { if (this.SubEvent != null) this.SubEvent(); } }
貓對被觀察者的影響
class Cat : Subject { public new event SubEventHandler SubEvent; public void Cry() { SubEvent(); Console.WriteLine("貓大叫!"); } }
然後老鼠跟主人都被貓影響,觀察者被被觀察者影響,產生不同的反應
interface Observer { void Response(); //觀察者的響應,如是老鼠見到貓的反映 }
老鼠觀察者的響應,產生逃跑反應
class MouseObserver { private string name; public MouseObserver(string name, Subject subj) { this.name = name; } public void Response() { Console.WriteLine(name + " 趕緊逃離!"); } }
主人觀察者的反應,吵死了
class MasterObserver { private string name; public MasterObserver(string name, Subject subj) { this.name = name; } public void Response() { Console.WriteLine(name + ":吵死了!"); } }
然後在交互端反饋出來是這樣的:
static void Main(string[] args) { Cat cat = new Cat(); MouseObserver mouse1 = new MouseObserver("mouse1", cat); MouseObserver mouse2 = new MouseObserver("mouse2", cat); MasterObserver Master = new MasterObserver("主人", cat); cat.SubEvent += new SubEventHandler(mouse1.Response); cat.SubEvent += new SubEventHandler(mouse2.Response); cat.SubEvent += new SubEventHandler(Master.Response); cat.Cry(); Console.ReadLine(); }
查看運行結果如下:
這樣處理過程就在客戶端進行,就不需要依賴抽象觀察者了