1. 程式人生 > >【設計模式】——觀察者模式

【設計模式】——觀察者模式

【觀察者模式】

 

觀察者模式定義了一種一對多的依賴關係,讓多個觀察物件同時監聽一個主題物件。這個主題物件再狀態發生變換時候,會通知所有觀察者物件,使他們能夠自動更新自己。

 

【介紹】

 

  • 主要解決:一個物件改變狀態給其他物件通知的問題

  • 何時使用:一個物件(目標物件)的狀態發生變化,所有的依賴物件(觀察者物件)都將得通知,進行廣播通知

  • 如何解決:使用面向物件技術,可以將這種依賴關係弱化

  • 關鍵程式碼:在抽象類裡有一個ArraList存放著觀察者

  • 優點:觀察者和被觀察者是抽象耦合的;建議一套觸發機制

  • 缺點:1、如果一個被觀察者物件有很多的直接和間接的觀察者,將所有的觀察者都通知到會花費很多時間。2、如果觀察者和被觀察者之間有迴圈依賴,被觀察者會觸發他們之間進行迴圈呼叫,可能導致系統崩潰。3、觀察者模式沒有相應的機制讓觀察者知道所觀察的目物件是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化

  • 注意事項:避免迴圈引用;如果順序執行,某一觀察者錯誤會導致系統卡死,一部採用非同步方式

 

【實現】

 

 

步驟一:subject類,為抽象主題提供一個介面


 

 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 o in observers)

            {

                o.Update();

            }

        }

    }

步驟二:observer類,抽象觀察者


 

abstract class Observer

    {

        public abstract void Update();

    }

步驟三:ConcreteSubject類,具體主題或者具體通知者


 

class ConcreteSubject:Subject

    {

        private string subjectState;

        //具體被觀察者狀態

        public string SubjectState

        {

            get { return subjectState; }

            set { subjectState = value; }

        }

    }

步驟四:ConcreteObserver類,具體觀察者

class ConcreteObserver:Observer

    {

        private string name;

        private string observerState;

        private ConcreteSubject subject;

        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);

        }

        public ConcreteSubject Subject

        {

            get { return subject; }

            set { subject = value; }

        }

    }

   

步驟五:客戶端程式碼


 

static void Main(string[] args)

        {

            ConcreteSubject s = new ConcreteSubject();

            s.Attach(new ConcreteObserver(s, "張三"));

            s.Attach(new ConcreteObserver(s,"李四"));



            s.SubjectState = "鬥地主";

            s.Notify();

            Console.Read();

        }

 

【總結】

 

1、將一個系統分割成一系列相互協作的類會導致需要維護相關物件間的一致性。我們不希望為了維持一致性而使各類緊密耦合,這樣會給維護、拓展、重用都帶來不便。

2、觀察者模式所阻東阿工作其實是在接觸耦合,讓耦合的雙方都依賴於抽象,而不是依賴於具體,從而使得各自的變化都不會影響另一邊的變化

3、委託是一種引用方法的型別,一旦為委託分配了方法,委託將與該方法具有完全相同的行為。委託方法的使用可以像其他任何方法一樣,具有引數和返回值。委託可以看作是對函式的抽象,是函式的“類”,委託的例項將代表一個具體的函式

4、委託物件所搭載的所有方法必須具有相同的原型和形式,也就是擁有相同的引數列表和返回值型別

5、一個委託可以搭載多個方法,所有方法被一次喚醒,它可以使得委託物件所搭載的方法並不需要屬於同一個類