設計模式(5)---觀察者模式

觀察者模式: ide

  

1、定義:this

  觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知全部觀察者對象,使它們可以自動更新本身。此種模式一般被用來實時事件處理系統。其中兩個重要對象是觀察者和主題,要想主題對象發生改變時,能通知到全部觀察者角色,則天然主題角色必須引用觀察者,從而完成觀察模式。spa

 

   特色:code

  一、定義了一對多的關係。server

  二、主題用一個共同的接口來更新觀察者。對象

  三、觀察者和主題用鬆耦合的方式結合,不須要知道實現細節,只須要實現接口就能夠。blog

 

2、UML類圖:接口

  

 

3、基本代碼:  事件

class Program
    {
        static void Main(string[] args)
        {
            ConcreteSubject cs = new ConcreteSubject();

            cs.Attach(new ConcreteObserver(cs, "x"));
            cs.Attach(new ConcreteObserver(cs, "y"));

            cs.SubjectState = "abc";
            cs.Notify();

            Console.Read();
        }
    }

    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 ob in observers)
            {
                ob.Update();
            }
        }
    }

    class ConcreteSubject : Subject
    {
        private string subjectState;
        public string SubjectState
        {
            get { return subjectState; }
            set { subjectState = value; }
        }
    }

    abstract class Observer
    {
        public abstract void Update();
    }

    class ConcreteObserver : Observer
    {
        private string name;
        private string observerState;
        private ConcreteSubject subject;
        public ConcreteSubject Subject
        {
            get { return subject; }
            set { subject = value; }
        }

        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);
        }  
    }
View Code

 

4、適用場景:get

  當一個對象的改變須要同時改變其餘對象時,並且不知道具體有多少對象有待改變時,應該考慮使用觀察者模式。

 

  舉例說明:

  

 

  實例代碼: 

interface ISubject
    {
        void Attach(Observer observer);
        void Detach(Observer observer);
        void Notify();
        string SubjectState { get; set; }
    }

    class Boss : ISubject
    {
        private IList<Observer> observers = new List<Observer>();
        private string bossAction;

        public string SubjectState
        {
            get { return bossAction; }
            set { bossAction = value; }
        }

        public void Attach(Observer observer)
        {
            observers.Add(observer);
        }

        public void Detach(Observer observer)
        {
            observers.Remove(observer);
        }

        public void Notify()
        {
            foreach (Observer ob in observers)
            {
                ob.Update();
            }
        }
    }

    abstract class Observer
    {
        protected string name;
        protected ISubject subject;

        public Observer(string name, ISubject subject)
        {
            this.name = name;
            this.subject = subject;
        }

        public abstract void Update();
    }

    class StockObserver : Observer
    {
        public StockObserver (string name,ISubject subject):base(name,subject )
        {}

        public override void Update()
        {
            Console.WriteLine("{0},{1} 關閉股票,繼續工做", subject.SubjectState, name);
        }
    }

    class NBAObserver : Observer
    {
        public NBAObserver (string name,ISubject subject):base(name,subject)
        {}

        public override void Update()
        {
            Console.WriteLine("{0},{1} 關閉NBA,繼續工做", subject.SubjectState, name);
        }
    }
View Code
Boss boss = new Boss();
            Observer s1 = new StockObserver("張三", boss);
            Observer s2 = new NBAObserver("李四", boss);
            boss.Attach(s1);
            boss.Attach(s2);
            boss.SubjectState = "老闆回來了";
            boss.Notify();

 

5、觀察者模式的缺點及解決方法:

  在具體前臺、同事和老闆的實例中,使用依賴倒轉原則,可是「抽象通知者」仍是依賴「抽象觀察者」,即若是沒有抽象觀察者這樣的接口,通知功能就完不成。另外就是每一個具體觀察者,它不必定是「更新」的方法要調用,多是其餘的方法。解決方法:通知者和觀察者之間根本互相不知道,由客戶端決定通知誰。對於前臺的實例,決定使用委託的方式來實現由客戶端來決定具體通知誰的功能。

  實例說明:

interface ISubject
    {
        void Notify();
        string SubjectState { get; set; }
    }

    public delegate void DelegateHandler();

    class Boss : ISubject
    {
        public event DelegateHandler Update;

        public string SubjectState { get; set; }

        public void Notify()
        {
            Update();
        }
    }

    abstract class Observer
    {
        protected string name;
        protected ISubject subject;

        public Observer(string name, ISubject subject)
        {
            this.name = name;
            this.subject = subject;
        }

        public abstract void Update();
    }

    class StockObserver : Observer
    {
        public StockObserver(string name, ISubject subject)
            : base(name, subject)
        { }

        public override void Update()
        {
            Console.WriteLine("{0},{1} 關閉股票,繼續工做", subject.SubjectState, name);
        }
    }

    class NBAObserver : Observer
    {
        public NBAObserver(string name, ISubject subject)
            : base(name, subject)
        { }

        public override void Update()
        {
            Console.WriteLine("{0},{1} 關閉NBA,繼續工做", subject.SubjectState, name);
        }
    }
View Code

 

Boss boss = new Boss();
            StockObserver s1 = new StockObserver("張三", boss);
            NBAObserver s2 = new NBAObserver("李四", boss);

            boss.Update += new DelegateHandler(s1.Update);
            boss.Update += new DelegateHandler(s2.Update);
            boss.SubjectState = "老闆回來了";
            boss.Notify();

 

 

6、總結:

  觀察者模式所作的工做其實就是在解除耦合。讓耦合的雙方都依賴於抽象,而不是依賴於具體,從而使各自的變化都不會影響到另外一邊的變化。

相關文章
相關標籤/搜索