標籤:
Observer 觀察者模式(行為型模式)
動機(Motivation)
在軟體構建過程中,我們需要為某些對象建立一種“通知依賴關係”——一個對象(目標對象)的狀態發生改變,所有依賴對象(觀察者對象)都將得到通知。如果這樣的以來對象關係過於緊密,將使軟體不能很好地抵禦變化。
使用物件導向技術,可以將這種依賴關係弱化,並形成一種穩定的依賴關係。從而實現軟體體繫結構的松耦合。
意圖(Intent)
定義對象間的一種一對多的依賴關係,以便當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並自動更新——《設計模式》GoF
範例程式碼
這是一個ATM取錢的例子:
public class ATM { private BankAccount bankAccount; //... void Process(int data) { bankAccount.Widthdraw(data); } } public class BankAccount { private Emailer emailer;//強依賴關係 private Mobile mobile;//強依賴關係 public void Widthdraw(int data) { //... UserAccountArgs args=new UserAccountArgs(); //... emailer.SendEmail(UserAccountArgs.UserEmail); mobile.SendNotification(UserAccountArgs.MobileNumber); } } public class Emailer { public void SendEmail(string userEmail) { //... } } public class Mobile { public void SendNotification(string mobileNumber) { //... } }
public class UserAccountArgs { public string UserEmail { get; set; } public string MobileNumber { get; set; } }
BankAccount和Emailer、Mobile是緊耦合的關係,需要解耦:
public class BankAccount { IList<IAccountObserver> observerList=new List<IAccountObserver>(); public void Widthdraw(int data) { //... UserAccountArgs args=new UserAccountArgs(); //... foreach (var accountObserver in observerList) { accountObserver.Update(args); } } public void AddObserver(IAccountObserver accountObserver) { observerList.Add(accountObserver); } public void RemoveObserver(IAccountObserver accountObserver) { observerList.Remove(accountObserver); } } public interface IAccountObserver { void Update(UserAccountArgs args); } public class Emailer : IAccountObserver { //public void SendEmail(string to) //{ // //... //} public void Update(UserAccountArgs args) { string userEmail = args.UserEmail; //... } } public class Mobile : IAccountObserver { //public void SendNotification(string to) //{ // //... //} public void Update(UserAccountArgs args) { string mobileNumber = args.MobileNumber; //... } } public class UserAccountArgs { public string UserEmail { get; set; } public string MobileNumber { get; set; } }
如果BankAccount的變化比較多,可以繼續抽象來解除與IAccountObserver的耦合:
public class BankAccount : Subject { public void Widthdraw(int data) { //... UserAccountArgs args=new UserAccountArgs(); //... Notify(args); } } public abstract class Subject { IList<IAccountObserver> observerList = new List<IAccountObserver>(); public void Notify(UserAccountArgs args) { //... foreach (var accountObserver in observerList) { accountObserver.Update(args); } } public void AddObserver(IAccountObserver accountObserver) { observerList.Add(accountObserver); } public void RemoveObserver(IAccountObserver accountObserver) { observerList.Remove(accountObserver); } }
這時BankAccount就和IAccountObserver解除耦合了。
演化過程
當寫軟體的時候,不一定要套用某個設計模式。為了應對變化,在解耦合的過程中,自然而然就用到了某種模式。
重要的是松耦合的設計思維。學習設計模式的意義在於深化設計思維。
結構(Structure)
Observer模式的幾個要點
- 使用物件導向的抽象,Observer模式使得我們可以獨立地改變目標與觀察者,從而使二者之間的依賴關係達致松耦合。
- 目標發送通知時,無需指定觀察者,通知(可以攜帶通知資訊作為參數)會自動傳播。觀察者自己決定是否要訂閱通知,目標對象對此一無所知。
- 在C#的event中,委託充當了Observer介面,而提供事件的對象充當了目標對象。委託是比抽象Observer介面更為松耦合的設計。
轉載請註明出處:
JesseLZJ
出處:http://jesselzj.cnblogs.com
設計模式18:Observer 觀察者模式(行為型模式)