C#設計模式系列:觀察者模式(Observer)

libingql發表於2014-04-01

  在軟體構建過程中,需要為某些物件建立一種“通知依賴關係”,即一個物件的狀態發生改變,所有的依賴物件都需要得到通知。

1、觀察者模式簡介

1.1>、定義

  定義物件間的一種一對多的依賴關係,當一個物件的狀態發生改變時,所有依賴於它的物件都得到通知並被自動更新。

1.2>、使用頻率

  

2、觀察者模式結構

2.1>、結構圖

2.2>、參與者

  觀察者模式參與者:

  ◊ Subject

    ° 抽象的主題,被觀察的物件

    ° 提供Attach和Detach Observer物件的介面

  ◊ ConcreteSubject

    ° 具體的被觀察物件,維持ConcreteSubject狀態。

    ° 當狀態發生變化時,傳送訊息通知它的觀察者。

  ◊ Observer:抽象的觀察者,定義一個傳送變化通知更新的介面。

  ◊ ConcreteObserver

    ° 維持一個對ConcreteSubject物件的引用

    ° 儲存subjects狀態

    ° 實現當Observer介面發生變動時,subjects狀態同步更新。

   在觀察者模式中,Subject通過Attach()和Detach()方法新增或刪除其所關聯的觀察者,並通過Notify進行更新,讓每個觀察者都可以觀察到最新的狀態。

3、觀察者模式結構實現

  Observer.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.ObserverPattern.Structural
{
    public abstract class Observer
    {
        public abstract void Update();
    }
}

  Subject.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.ObserverPattern.Structural
{
    public class Subject
    {
        private List<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();
            }
        }
    }
}

  ConcreteSubject.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.ObserverPattern.Structural
{
    public class ConcreteSubject : Subject
    {
        private string _subjectState;

        /// <summary>
        /// Gets or sets subject state
        /// </summary>
        public string SubjectState
        {
            get { return _subjectState; }
            set { _subjectState = value; }
        }
    }
}

  ConcreteObserver.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DesignPatterns.ObserverPattern.Structural
{
    public 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("Observer {0}'s new state is {1}", _name, _observerState);
        }

        public ConcreteSubject Subject
        {
            get { return _subject; }
            set { _subject = value; }
        }
    }
}

  Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using DesignPatterns.ObserverPattern.Structural;

namespace DesignPatterns.ObserverPattern
{
    class Program
    {
        static void Main(string[] args)
        {
            // Configure Observer pattern
            ConcreteSubject s = new ConcreteSubject();

            s.Attach(new ConcreteObserver(s, "X"));
            s.Attach(new ConcreteObserver(s, "Y"));
            s.Attach(new ConcreteObserver(s, "Z"));

            // Change subject and notify observers
            s.SubjectState = "ABC";
            s.Notify();
        }
    }
}

  執行輸出:

Observer X's new state is ABC
Observer Y's new state is ABC
Observer Z's new state is ABC
請按任意鍵繼續. . .

4、觀察者模式應用分析

  觀察者模式適用情形:

  ◊ 當一個抽象模型有兩個方面,其中一方面依賴於另一方面。將這二者封裝在獨立的物件中以使它們可以各自獨立地改變和複用。

  ◊ 當對一個物件的改變需要同時改變其他物件,而不需要知道具體有多少物件有待改變。

  ◊ 當一個物件必須通知其他物件,而它又不需要知道其它的通知物件是誰,那些其它物件是誰不影響它傳送通知這件事。

  觀察者模式特點:

  ◊ 使用物件導向的抽象,Observer模式使得可以獨立地改變目標與觀察者,從而使二者之間的依賴關係達到鬆耦合。

  ◊ 目標傳送通知時,無需指定觀察者,通知會自動傳播。觀察者自己決定是否需要訂閱通知。

  ◊ 在C#中的Event。委託充當了Observer介面,而提供事件的物件充當了目標物件,委託是比抽象Observer介面更為鬆耦合的設計。

相關文章