天天看點

設計模式之觀察者模式

UML類圖:

設計模式之觀察者模式

舉一個生活中的例子:假如一個寫字樓的員工定了外賣。是定外賣的人每10分鐘就到樓下轉一圈兒看外賣到了。還是送外賣的小哥一個個工位的送過去?

都不是。

實際上外賣小哥到了寫字樓樓下給每個員工打電話,員工就會下樓拿着自己外賣上樓。

實際上,這就是一個觀察者模式。外賣小哥到寫字樓樓下--》自己的狀态改變了---》通過手機通知所有的觀察者

觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題。這個主題對象發生變化時,會通知所有觀察者對象,使他們能夠自動更新自己。

  • Subject:抽象主題,抽象主題裡包含了一個list,這個list是所有的observer,你可以通過atach添加一個observer,也可以通過detach删掉一個observer。還包含了一個

Notify函數,這個函數可以調用所有observer的update函數,來更新自己的狀态。

  • Observer:為所有的具體觀察者提供了一個接口update。
  • ConcreteSubject:具體主題,也就是具體的被觀察者。裡面包含了自己的state資訊。
  • ConcreteObserver:具體的觀察者,觀察者裡面可以包含一個所相關的主題對應的state資訊,以及一個實作了的update函數,當調用這個update函數時候,修改自己的state資訊。舉一個例子,假如被觀察是消費者,當消費者已經付錢,表示狀态變化,觀察者1——出納員的state改變就是登記入賬,觀察者2——會計來開發票,觀察者3——配送員來發貨。
/// <summary>
    /// 抽象主題類
    /// </summary>
    public abstract class Subject
    {
        private IList<Observer> observers = new List<Observer>();

        /// <summary>
        /// 增加觀察者
        /// </summary>
        /// <param name="observer"></param>
        public void Attach(Observer observer)
        {
            observers.Add(observer);
        }

        /// <summary>
        /// 移除觀察者
        /// </summary>
        /// <param name="observer"></param>
        public void Detach(Observer observer)
        {
            observers.Remove(observer);
        }

        /// <summary>
        /// 向觀察者(們)發出通知
        /// </summary>
        public void Notify()
        {
            foreach (Observer o in observers)
            {
                o.Update();
            }
        }
    }

    /// <summary>
    /// 抽象觀察者類,為所有具體觀察者定義一個接口,在得到通知時更新自己
    /// </summary>
    public abstract class Observer
    {
        public abstract void Update();
    }

    /// <summary>
    /// 具體觀察者或具體通知者,将有關狀态存入具體觀察者對象;在具體主題的内部狀态改變時,給所有登記過的觀察者發出通知。具體主題角色通常用一個具體子類實作。
    /// </summary>
    public class ConcreteSubject : Subject
    {
        private string subjectState;

        /// <summary>
        /// 具體觀察者的狀态
        /// </summary>
        public string SubjectState
        {
            get { return subjectState; }
            set { subjectState = value; }
        }
    }

    /// <summary>
    /// 具體觀察者,實作抽象觀察者角色所要求的更新接口,已是本身狀态與主題狀态相協調
    /// </summary>
    public class ConcreteObserver : Observer
    {
        private string observerState;
        private string name;
        private ConcreteSubject subject;

        /// <summary>
        /// 具體觀察者用一個具體主題來實作
        /// </summary>
        public ConcreteSubject Subject
        {
            get { return subject; }
            set { subject = value; }
        }

        public ConcreteObserver(ConcreteSubject subject, string name)
        {
            this.subject = subject;
            this.name = name;
        }

        /// <summary>
        /// 實作抽象觀察者中的更新操作
        /// </summary>
        public override void Update()
        {
            observerState = subject.SubjectState;
            Console.WriteLine("The observer's state of {0} is {1}", name, observerState);
        }
    }      

用戶端:

class Program
    {
        static void Main(string[] args)
        {
            // 具體主題角色通常用具體自來來實作
            ConcreteSubject subject = new ConcreteSubject();

            subject.Attach(new ConcreteObserver(subject, "Observer A"));
            subject.Attach(new ConcreteObserver(subject, "Observer B"));
            subject.Attach(new ConcreteObserver(subject, "Observer C"));

            subject.SubjectState = "Ready";
            subject.Notify();

            Console.Read();
        }
    }      

繼續閱讀