C#設計模式之3:觀察者模式


C#中已經實現了觀察者模式,那就是事件,事件封裝了委托,使得委托的封裝性更好,在類的內部定義事件,然后在客戶端對事件進行注冊:

 public class Subject
    {
        public event Action<int> MyEvent;
        public async Task ExecuteEvent()
        {
            for (int i = 0; i < 100; i++)
            {
                await Task.Delay(TimeSpan.FromSeconds(0.1));
                Console.Write(".");
                if (i>50)
                {
                    MyEvent(i);
                    return;
                }
            }            
        }

    }
 class Program
    {
        static void Main(string[] args)
        {
            Subject sub = new Subject();
            sub.MyEvent += (a) =>
            {
                Console.WriteLine($"the temprature is {a} now ,please shutdown!");              
            };
            Task task= sub.ExecuteEvent();          
            Console.ReadKey();
        }
    }

可以說在C#中實現觀察者模式是非常方便的。

觀察者模式的定義:觀察者模式定義了對象之間的一對多的依賴,這樣一來,當一個對象改變狀態時,他的所有依賴着都會收到通知並自動更新。

上面的例子可能比較簡單,Subject類充當的就是一個主題,或者叫發布者,使用+=注冊的lambda充當的就是一個訂閱者,也就是Observer,(lambda表達式會生成一個匿名的類,更准確的說實際上這個匿名的類就是一個Observer)將會有很多的類似於這樣的訂閱者來對Subject的MyEvent事件進行注冊,所以Subject和Observer是一對多的。當我們執行Subject中的ExecuteEvent方法時,就是在滿足一定條件后發出通知,而Observer就會去執行相應的動作,這就是觀察者模式。因為這個模式涉及到了對象和對象之間的依賴,這么這里又涉及到一個概念,那就是耦合。

設計原則:為了交互對象之間的松耦合而努力。

 

手動實現的觀察者模式(java)

還是以headfirst設計模式這本書上的例子為依據,這個例子講的是一個氣象站(ISubject)和很多布告板(Observer)的故事,先上類圖:

 

 觀察者模式中有兩個角色,一個是Subject,主題角色,這個角色用來發布消息,另一個是Observer,觀察者,用來接收消息。Subject和Observer的關系是一對多。

 /// <summary>
    /// 定義一個主題對象的接口,主題對象可以發出通知。
    /// 被觀察者(IObserver)接受並做出相應的動作。
    /// 主題對象和觀察者之間是一對多的關系。
    /// </summary>
    public interface ISubject
    {
        void RegisterObserver(IObserver observer);
        void RemoveObserver(IObserver observer);
        void NotifyObservers();
    }

    public interface IObserver
    {
        void Update(float temp, float humidity, float pressure);
    }

    public interface IDisplay
    {
        void Display();
    }
    /// <summary>
    /// ConcreteSubject角色
    /// </summary>
    public class WeatherData:ISubject
    {
        private readonly IList<IObserver> _observers=new List<IObserver>();
        public float Temp { get; set; }
        public float Humidity { get; set; }
        public float Pressure { get; set; }
        public void RegisterObserver(IObserver observer)
        {
           _observers.Add(observer);
        }

        public void RemoveObserver(IObserver observer)
        {
            _observers.Remove(observer);
        }

        public void NotifyObservers()
        {
            foreach (IObserver item in _observers)
            {
               item.Update(Temp,Humidity,Pressure);
            }
        }


        public void SetMeasurements(float temp, float humidity, float pressure)
        {
            Temp = temp;
            Humidity = humidity;
            Pressure = pressure;
            NotifyObservers();            
        }
    }
    public class CurrentConditionDisplay:IObserver,IDisplay
    {
        private float _temperature;
        private float _humidity;
        private ISubject _weatherData;
        public CurrentConditionDisplay(ISubject weatherData)
        {
            _weatherData = weatherData;
            _weatherData.RegisterObserver(this);
        }
        public void Update(float temperature, float humidity, float pressure)
        {
            _temperature = temperature;
            _humidity = humidity;
            Display();
        }
        public void Display()
        {
            Console.WriteLine($"out temperature is {_temperature},out humidity is {_humidity}");
        }
       
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM