1. 程式人生 > >Head First設計模式——觀察者模式

Head First設計模式——觀察者模式

前言: 這篇文章我們以Head First設計模式中講解的氣象站為例,通過它的案列進行學分析和編碼(C#)測試,並歸納總結出觀察者模式。

1、氣象監測案列,錯誤示範實現

一個氣象站,分別有三個裝置:溫度感應裝置,溼度感應裝置,氣壓感應裝置。WeathData物件跟蹤氣象站資料,WeathData有MeasurmentsChanged()方法,當感應裝置資料變化後就會呼叫MeasurmentsChanged對使用改資料的使用者進行資料更新。目前需求是要三個佈告板,分別是目前氣象資料狀況佈告板(CurrentConditionDisply)、氣象資料統計佈告板(StaisticsDisply)、天氣預報佈告板(ForcastDisply)。三塊佈告板都是需要接收氣象站資料,然後按需展示到佈告板上。針對這個需求我們可以如下方式實現:

public class WeatherData(){
    private float Temperature{get;set;}
    private float Humidity{get;set;}
    private float Pressure{get;set;}

    public void MeasurmentsChanged(){
        CurrentConditionDisply.Update(Temperature,Humidity,Pressure);
        StaisticsDisply.Update(Temperature,Humidity,Pressure);
        ForcastDisply.Update(Temperature,Humidity,Pressure);
    }
}

public class CurrentConditionDisply{
    public void Update(float temperature,float humidity,float Pressure){
        //更新公佈資料
    }
}
public class StaisticsDisply{
    public void Update(float temperature,float humidity,float Pressure){
        //更新統計資料
    }
}
public class ForcastDisply{
    public void Update(float temperature,float humidity,float Pressure){
        //更新天氣預報
    }
}

 WeatherData是資料跟蹤物件,當氣象站資料變化時用MeasurmentsChanged方法來依次呼叫三塊佈告板的Update方法更新氣象資料。按照這種設計能實現目前需求,但是如果新加入一種佈告板或者刪除一個佈告板,那麼我們需要去修改MeasurmentsChanged方法新增或者刪除程式碼,這就會造成後期的維護擴充套件問題。這個例子暴露的問題:

1、我們是針對實現程式設計,而非針對介面。

2、對於每個新的佈告板,我們都得修改程式碼。

3、無法在執行時動態地增加或者刪除佈告板。

4、未封裝改變的部分,違反了對修改關閉,對擴充套件開放原則。

2、使用觀察者模式解耦

由1的實現和帶來的問題以及它的場景我們可以使用設計模式中的觀察者模式很好的滿足這一需求,且後面的維護擴充套件都很方便。首先我們先了解觀察者模式

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

訂閱報紙就是典型的觀察者模式,出版社即為主題(subject),訂閱者即是觀察者(observer),當有新報紙時,報社就會派人送新報紙到訂閱了該報紙的讀者手上。我們通過觀察者模式類圖進行理解我記憶,然後我們再對之前的氣象站進行觀察者模式封裝修改。

3、利用觀察者模式改進氣象站

按照觀察者模式我們需要定義一個主題介面Subject,WeatherData作為具體的主題類繼承介面Subject,實現註冊移除通知觀察者介面。定義Observer介面,其他三塊佈告板繼承Observer實現自己的更新資料方法Update。

    /// <summary>
    /// 主題
    /// </summary>
    public interface Subject
    {
        public void RegisterObserver(Observer o);
        public void RemoveObserver(Observer o);
        public void NotifyObserver();
    }
    /// <summary>
    /// 具體主題(氣象站)
    /// </summary>
    public class WeatherData : Subject
    {
        private List<Observer> observers;
        private float Temperature { get; set; }
        private float Humidity { get; set; }
        private float Pressure { get; set; }

        public WeatherData()
        {
            observers = new List<Observer>();
        }
        public void RegisterObserver(Observer o)
        {
            observers.Add(o);
        }

        public void RemoveObserver(Observer o)
        {
            observers.Remove(o);
        }

        //通知觀察者
        public void NotifyObserver()
        {
            foreach (var o in observers)
            {
                o.Update(Temperature, Humidity, Pressure);
            }
        }

        public void MeasurmentsChanged()
        {
            NotifyObserver();
        }

        //資料變化
        public void SetMeasurments(float temperature, float humidity, float pressure)
        {
            Temperature = temperature;
            Humidity = humidity;
            Pressure = pressure;
            MeasurmentsChanged();
        }
    }

    /// <summary>
    /// 訂閱者
    /// </summary>
    public interface Observer
    {
        void Update(float temperature, float humidity, float pressure);
    }

    public class CurrentConditionDisply : Observer
    {
        private Subject weatherData;
        public CurrentConditionDisply(Subject weatherData)
        {
            this.weatherData = weatherData;
            weatherData.RegisterObserver(this);
        }
        public void Update(float temperature, float humidity, float pressure)
        {
            Console.WriteLine($"當前情況佈告板:{temperature},{humidity},{pressure}");
        }
    }
    public class StaisticsDisply : Observer
    {
        private Subject weatherData;
        public StaisticsDisply(Subject weatherData)
        {
            this.weatherData = weatherData;
            weatherData.RegisterObserver(this);
        }
        public void Update(float temperature, float humidity, float pressure)
        {
            Console.WriteLine($"統計資料佈告板:{temperature},{humidity},{pressure}");
        }
    }
    public class ForcastDisply : Observer
    {
        private Subject weatherData;
        public ForcastDisply(Subject weatherData)
        {
            this.weatherData = weatherData;
            weatherData.RegisterObserver(this);
        }
        public void Update(float temperature, float humidity, float pressure)
        {
            Console.WriteLine($"天氣預報佈告板:{temperature},{humidity},{pressure}");
        }
    }

對使用了觀察者模式的氣象站進行測試,當資料變化的時候就會自動通知觀察者並更新資料,也可以靈活的新增移除觀察者而不用去具體的實現裡面修改程式碼。

        static void Main(string[] args)
        {
            WeatherData weatherData = new WeatherData();
            CurrentConditionDisply currentConditionDisply = new CurrentConditionDisply(weatherData);
            StaisticsDisply staisticsDisply = new StaisticsDisply(weatherData);
            ForcastDisply forcastDisply = new ForcastDisply(weatherData);
            weatherData.SetMeasurments(30, 65, 30.5F);
            Console.WriteLine("---------------移除訂閱者-----------");
            weatherData.RemoveObserver(currentConditionDisply);
            weatherData.SetMeasurments(31,55,20);
            Console.WriteLine("---------------新增訂閱者-----------");
            weatherData.RegisterObserver(currentConditionDisply);
            weatherData.SetMeasurments(30, 55, 30.5F);
            Console.ReadKey();
        }

  

相關推薦

Head First設計模式——觀察模式

前言: 這篇文章我們以Head First設計模式中講解的氣象站為例,通過它的案列進行學分析和編碼(C#)測試,並歸納總結出觀察者模式。 1、氣象監測案列,錯誤示範實現 一個氣象站,分別有三個裝置:溫度感應裝置,溼度感應裝置,氣壓感應裝置。WeathData物件跟蹤氣象站資料,WeathData有Meas

設計模式——觀察模式(C++實現)

ace mes des ret rtu cto pattern virt date 1 #include <iostream> 2 #include <vector> 3 #include <algorithm>

C#設計模式--觀察模式(發布-訂閱模式

工廠方法 設計 解決 line strac itl names spa ret 0.C#設計模式--簡單工廠模式 1.C#設計模式--工廠方法模式 2.C#設計模式--抽象工廠模式 3.C#設計模式--單例模式 4.C#設計模式--建造者模式 5.C#設計模式--

設計模式觀察模式

5.1 servers 監聽 val notify src [] ati 場景 1 定義   觀察者模式,有時又稱為發布-訂閱模式。定義了一種一對多個依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己

c#設計模式-觀察模式

正在 pro 描述 設計 abstract logs 名單 ron alt Observer 與 Subject 互為耦合,但是這種耦合的雙方都依賴於抽象,而不依賴於具體。 一、觀察者模式 目的 概述 原理 二、 C#中的觀察者模式 概述 模型與觀察者基類 優點 三、

三國設計模式——觀察模式

efault bre ati fault println bst imp default mman 1 package observer; 2 3 public abstract class ObserverGenerals { 4 5 protect

項目中用到的設計模式-觀察模式

道理 generated 商家 商城項目 bean boolean collect 相關 not 一:觀察者模式簡單介紹   觀察者模式又稱為發布-訂閱模式(publish/subscribe),該模式定義了一種,一對多的依賴關系,讓多個觀察者同時監聽一個主題對像,這個主題

Java 設計模式 觀察模式

例如 null 可能 truct pri color img cte bstr   在閻宏博士的《JAVA與模式》一書中開頭是這樣描述觀察者(Observer)模式的:觀察者模式是對象的行為模式,又叫發布-訂閱(Publish/Subscribe)模式、模型-視圖(Mode

Python設計模式——觀察模式

val property 創建倉庫 tool return observe send als 工作流 例子1:class Service: def __init__(self, service_name, process_name, port, enable_mon

Java設計模式---------觀察模式

個人 api 如果 修改 沒有 zed return pla 細節 以下內容主要來自《HeadFirst設計模式》一書和博文:http://www.cnblogs.com/xrq730/p/4908686.html,僅作為個人的學習筆記使用。 觀察者模式 定義了對象之間的一

設計模式——觀察模式

param body 抽象 logs ring 依賴 ret rip system - 什麽是觀察者模式 觀察者模式有叫做發布訂閱模式,是對象間一種一對多的依賴關系,是的每當一個對象改變狀態時,則所有依賴於他的對象都會得到通知並自動更新。這其中過程就好比訂閱微信公眾號,公眾

設計模式-觀察模式

設計模式 觀察者模式 //主題 interface Subject { void Notify(); string msg { get; set; } UpdateHandler Update { get; set; } } de

Java常用設計模式——觀察模式

ray stat param servers face oid println override 角色 觀察者模式又叫做發布-訂閱-模式、模型-視圖-模式、源-監聽器-模式或者從屬者模式。觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對

設計模式----觀察模式通俗實例

接口 pack ceo 軟件 依賴關系 http In array value 觀察者模式(一對多的依賴關系):主題對象發生變化時候,通知所有依賴該對象的觀察者對象,使得觀察者對象更新。 被觀察的對象:主題 依賴的對象:觀察者 例子:例如一個軟件更新版本了,會通知用戶

android 開發設計模式---觀察模式

嚴格 oid line eventbus 否則 post vat 關系 lock 情景1 有一種短信服務,比如天氣預報服務,一旦你訂閱該服務,你只需按月付費,付完費後,每天一旦有天氣信息更新,它就會及時向你發送最新的天氣信息。 情景2 雜誌的訂閱,你只需向郵局

設計模式中的黃金搭檔(一對活寶):命令模式+觀察模式

現有場景描述:現在無論是系統自帶的鍵盤還是第三方的鍵盤一般都自帶撤銷和恢復功能,你知道它們是用的什麼模式實現的嗎?它們用的是==命令模式+觀察者模式==,你答對了嗎?簡單科普一下啥是==Command模式==? Command模式:- 模式型別:行為類模式- 定義:將一個操作、一個方法呼叫、一個命令封裝成一個

android設計模式——觀察模式

定義:物件間一種一對多的依賴關係,使得一個物件改變狀態,則所有依賴於他的物件都會得到通知並被自動更新 使用場景: 關聯行為場景。 事件多級觸發場景 跨系統的訊息交換場景。如訊息佇列,事件匯流排的處理機制。 應用舉例:觀察者訂閱被觀察者的狀態,當被觀察者狀態改變的時候

設計模式----觀察模式 【含例項】

日常學習C++設計模式中... 給自己留個備份,有問題歡迎溝通交流。 好了,開始嘍~ --------------------------------------------------------------------------------------------------

Ruby設計模式-觀察模式學習筆記

nco utf-8 upd attr ttr rim chan utf ade observer.rb #!/bin/env ruby # encoding: utf-8 require ‘observer‘ class CriminalMovement incl

java常用設計模式--觀察模式簡單例子

package com.ruanyun;import java.util.List;import java.util.Vector;/** * @Auther: maxw * @Date: 2018/11/10 16:14 * @Description:觀察者模式 * 基本概念: * 觀察者模式屬於行為型模式