觀察者模式(七)

觀察者模式

定義:數組

咱們能夠把觀察目標理解爲主動方、發佈方、主體等;把觀察者理解爲被動方、訂閱方、觀察器等。目標是整個行爲鏈的源頭,其它觀察者都依賴於它的變化而做出響應。爲了實現低耦合,咱們不能使用「直接調用」的方式而須要利用「訂閱(清單)-通知」的機制去完成設計。通俗地說就是觀察者向目標「訂閱」它的改變,而目標發生改變後就「通知」全部已經「訂閱」了它的改變的觀察者,從而執行「訂閱」的內容。這種機制的好處在於下降耦合度,分工明確,目標只負責在自身狀態發生改變或作出某種行爲時向自身的訂閱清單發出「通知」,而不是直接調用觀察者的行爲(方法);觀察者只負責向目標「訂閱」它的變化,以及定義自身在收到目標「通知」後所須要作出的具體行爲(也就是訂閱的內容)。就像咱們向出版社訂閱報刊同樣,出版社有新一期報刊發行時並非直接跟每位訂閱者聯繫,而是「通知」訂閱者名單按順序給每位訂閱者發送所訂報刊。安全

 

優勢:ide

經過對模型與觀察者基類的分析可知,委託與事件的機制幾乎消除了這兩個模塊之間的耦合,靈活性提升了不少。若是須要增長觀察者,則只須要覆蓋基類抽象方法及把觀察目標傳遞給基類。函數

 

案例 1:測試

有一個拍賣師和諾幹買家進行一個藝術品拍賣,這裏咱們使用觀察者模式。這裏的拍賣師爲被觀察者,買家是觀察者。this

public abstract class observer//首先要建立一個觀察者基類
{
    public abstract void QuotedPrice();//觀察者的報價
       
}




 public abstract class Subject//拍賣者基類
    {
        public ArrayList observers = new ArrayList();//用於存儲觀察者的數組
        public int _price;//拍賣價格

        public void AddObserver(observer person)//添加觀察者
        {
            observers.Add(person);
            Console.WriteLine("......{0}加入拍賣",person);
        }

        public void DeleteObserver(observer person)//刪除觀察者
        {
            observers.Remove(person);
            Console.WriteLine("......{0}退出拍賣", person);
        }

        public virtual void QuotedPrice()//通知每個觀察者如今的價格
        {
            for (int i = observers.Count - 1; i >= 0 ; i--)
            {
                ((observer)observers[i]).QuotedPrice();
            }
        }

        public bool IsOver//是否拍賣結束
        {
            get
            {
                if (observers.Count == 0 || observers.Count == 1)
                    return true;
                else
                    return false;
            }
        }
    }



 public class SubjectArt:Subject//具體的拍賣者類
    {
        public SubjectArt(int _price)//構造函數,構造時,肯定起拍價。
        {
            this._price = _price;
        }

        public int Price//如今的拍賣價格
        {
            get
            {
                return this._price;
            }
            set
            {
                if (this._price > value)
                    return;
                else
                    _price = value;
            }
        }

        public override void QuotedPrice()//拍賣者出家
        {
            base.QuotedPrice();

            if (observers.Count == 1)
            {
                Console.WriteLine("{0}最終勝出,最終報價爲{1}", observers[0], this.Price);
            }
            else if (observers.Count == 0)
            {
                Console.WriteLine("本次競拍流拍...");
            }


        }
    }



public class observerArt:observer//具體的買家類
    {
        private int _price;//當前買家的出家
        private int _topPrice;//買家最高的心理價位
        private string _name;//買家的名字

        private SubjectArt _subjectArt;//持有拍賣者的引用
        public observerArt(string Name,int price,int topPrice, SubjectArt subjectArt)//根據參數進行構造,並把本身做爲買家註冊給拍賣者
        {
            this._name = Name;
            this._price = price;
            this._topPrice = topPrice;
            this._subjectArt = subjectArt;
            this._subjectArt.AddObserver(this);
        }
        public override void QuotedPrice()//買家是否再進行出家或者退出
        {
            if (this._price > _topPrice)
            {
                Console.WriteLine("{0}退出,當前最高價格{1}", this._name, _subjectArt._price);
                this._subjectArt.DeleteObserver(this);
            }
            else
            {
                this._price += 1;
                this._subjectArt.Price = this._price;
                if (this._price >= this._subjectArt.Price)
                {
                    Console.WriteLine("{0}報出最新價格:{1}",this._name,this._price);       
                }

            }
        }
    }







==================================進行測試===================================================
 class Program
    {
        static void Main(string[] args)
        {
            SubjectArt subjectArt = new SubjectArt(5);
            observerArt personOne = new observerArt("張曉坤",5,15, subjectArt);
            observerArt personTwo = new observerArt("張婷婷", 5, 13, subjectArt);
            observerArt personThree = new observerArt("王小明", 5, 11, subjectArt);
            observerArt personFour = new observerArt("李麗", 5, 14, subjectArt);
            observerArt personFive = new observerArt("劉偉", 5, 10, subjectArt);
            int n = 0;
            while (!subjectArt.IsOver)
            {
                Console.WriteLine("====第{0}輪競拍========",n);
                subjectArt.QuotedPrice();
                n++;
            }
            Console.ReadKey();

        }
    }

案例2:spa

有一個劫匪搶劫了一家銀行後逃跑了,有警察追捕他,好心市民看到劫匪會通知警察,劫匪的妻子知道劫匪缺錢後會給他匯錢。這樣咱們用觀察者模式來描述這些,劫匪是被觀察者,而警察、好心市民和劫匪妻子都是觀察者。如下爲代碼:設計

public abstract class ObserverMan//觀察者的抽象類
    {
        public abstract void Update();
        
    }


 public abstract class SubjectMan//被觀察者的抽象類
    {
        public List<ObserverMan> observers = new List<ObserverMan>();//全部觀察者存儲集合
        public string location = "";//劫匪要逃亡的地點

       
        /// <summary>
        /// 添加觀察者
        /// </summary>
        /// <param name="man"></param>
        public virtual void Attact(ObserverMan man)
        {
            observers.Add(man);
        }

        /// <summary>
        /// 移除觀察者
        /// </summary>
        /// <param name="man"></param>
        public virtual void Dettact(ObserverMan man)
        {
            observers.Remove(man);
        }

        /// <summary>
        /// 通知全部的觀察者去作某件事
        /// </summary>
        public virtual void MessageObserverAll()
        {
            for (int i = 0; i < observers.Count; i++)
            {
                observers[i].Update();
            }
        }
    }




public class SubjectBadMan:SubjectMan//具體的劫匪類
    {
        string Name;//劫匪的名字
        public SubjectBadMan(string _name)//劫匪的構造函數
        {
            this.Name = _name;
        }

        public void RunAway(string _location)//逃跑到某個地方
        {
           
            this.location = _location;
            Console.WriteLine("歹徒{0}逃到了{1}",this.Name,this.location);
            if (this.observers.Count == 0)
            {
                Console.WriteLine("你已經安全了,不用再逃亡了....");
            }
            base.MessageObserverAll();
        }

    }




 public class Police:ObserverMan//警察觀察者
    {
        SubjectBadMan badMan = null;
        public Police(SubjectBadMan _badMan)
        {
            this.badMan = _badMan;
            this.badMan.Attact(this);//警察註冊觀察者

        }
        public override void Update()//警察要作的事
        {
            var location = this.badMan.location;
            Console.WriteLine("警察 :歹徒已經逃到了{0},趕快部署警力抓捕。",location);
        }
    }

    public class Citizen : ObserverMan//熱心市民觀察者
    {
        SubjectBadMan badMan = null;
        public Citizen(SubjectBadMan _badMan)
        {
            this.badMan = _badMan;
            this.badMan.Attact(this);//熱心市民註冊觀察者
        }
        public override void Update()//熱心市民要作的事
        {
            var location = this.badMan.location;
            Console.WriteLine("熱心市民:歹徒已經逃到了{0},警察趕忙去抓啊", location);
        }
    }


    public class Wife : ObserverMan//妻子要作的事
    {
        SubjectBadMan badMan = null;
        public Wife(SubjectBadMan _badMan)
        {
            this.badMan = _badMan;
            this.badMan.Attact(this);//妻子註冊觀察者

        }
        public override void Update()
        {
            var location = this.badMan.location;
            Console.WriteLine("妻子:你到{0}了啊,我給你匯點錢", location);
        }
    }





===========================================進行測試==========================================

            SubjectMan badMan = new SubjectBadMan("張亭亭");
            ObserverMan police = new Police(badMan as SubjectBadMan);
            ObserverMan citizen = new Citizen(badMan as SubjectBadMan);
            ObserverMan wife = new Wife(badMan as SubjectBadMan);
            SubjectBadMan man;
            man = badMan as SubjectBadMan;
            man.RunAway("上海");
            Console.WriteLine();
            man.Dettact(wife);
            man.RunAway("廣州");
            Console.WriteLine();
            man.Dettact(citizen);
            man.RunAway("美國");
            Console.WriteLine();
            man.Dettact(police);
            man.RunAway("澳大利亞");
            Console.WriteLine();
            Console.ReadKey();

 

使用事件和委託來實現觀察者模式

相關文章
相關標籤/搜索