設計模式:觀察者模式

設計模式多是一個高深的問題,目測逼格極高,駕馭起來也確定是有難度的,爲了理解一篇文章中的一些概念,我也第一次鼓起勇氣直面了這個問題,雖然是初出茅廬的小菜鳥,但也是有一番收穫的,這篇文章粗淺的認識了觀察者模式,將會以一個氣象站的例子加以描述.
ios

觀察者模式

簡要的描述

觀察者模式,還有一個別名,叫作發佈-訂閱模式,相比於觀察者模式這個名稱來講,後者更具備表現力,觀察者模式有兩個主角,一個叫作Observer, 另外一個叫作Subject.
下面給出一些比較官方的東西,觀察者模式的組成c++

  1. 抽象目標角色 (Subject): 目標角色知道它的觀察者,能夠有任意多個觀察者觀察同一個目標。而且提供註冊和刪除觀察者對象的接口。目標角色每每由抽象類或者接口來實現。
  2. 抽象觀察者角色(Observer): 爲那些在目標發生改變時須要得到通知的對象定義一個更新接口。抽象觀察者角色主要由抽象類或者接口來實現。
  3. 具體目標角色(Concrete Subject): 將有關狀態存入各個Concrete Observer對象。當它的狀態發生改變時, 向它的各個觀察者發出通知。
  4. 具體觀察者角色(Concrete Observer): 存儲有關狀態,這些狀態應與目標的狀態保持一致。實現Observer的更新接口以使自身狀態與目標的狀態保持一致。在本角色內也能夠維護一個指向Concrete Subject對象的引用。

不過概念老是抽象的, 死板的定義每每不能給出直觀的感覺, 在詳細的解說以前, 咱們還須要瞭解觀察者模式到底要實現什麼目的, 這樣咱們也能夠進行有目的的學習.設計模式

For What ?

觀察者模式每每會被用於知足這樣的需求: 一個對象的狀態發生變化, 其餘對象也要隨之做出變化.函數

觀察者模式應該容許一個Concrete Subject有若干個Concrete Observer對其進行觀察, 當Concrete Subject的狀態發生改變時, 該模式能夠通知全部該Concrete Subject的Concrete Observer,而且這些觀察者會做出相應的改變, 而不是Concrete Subject的觀察者對象不該該受到任何通知.學習

假設一個氣象站管理了3個佈告板和一個氣象中心, 該模式能夠實如今氣象中心有新的氣象信息時,3個佈告板都能受到通知,而且能夠以本身的方式展現這些信息.this

該模式致力於下降對象之間的耦合性.spa

詳細講解

使用氣象站例子
語言: c++.net

/*
*設計模式之觀察者模式實驗代碼
*/
#include <iostream>
#include <vector>
using namespace std;
//Observer 抽象類 抽象目標角色(或稱主題)
class Observer{
public:
    ///update方法 收到通知時會執行這個方法
    virtual void update(float temp, float humidity, float pressure) = 0;
};
//Subject 抽象類
class Subject{
public:
    virtual void registerObserver(Observer* o) = 0; //註冊本身的觀察者
    virtual void removeObserver(Observer* o) = 0;   //將本身從該觀察者中移除
    virtual void notifyObserver() = 0;              //通知全部觀察者
};
//展現抽象類
class Display{
public:
    //將數據傳遞給外部
    virtual void display() = 0;

};


//訂閱的目標數據 天氣狀況 屬於——具體目標角色(Concrete Subject)
//繼承於Subject 
class WeatherData : public Subject{
private:
    std::vector<Observer*> observerVector;
    float temperature;
    float humidity;
    float pressure;
public:
    WeatherData(){
        //構造函數
    }
    ~WeatherData(){

    }
    virtual void registerObserver(Observer *o){
        observerVector.push_back(o);
    }
    virtual void removeObserver(Observer *o){
        std::vector<Observer*>::iterator it;
        for(it = observerVector.begin(); it != observerVector.end(); ++it){

            if((*it) == o){
                observerVector.erase(it);
                break;
            }
        }
    }
    //實現通知觀察者接口 遍歷全部觀察者 執行update 觀察者獲取到數據
    virtual void notifyObserver(){
        std::vector<Observer*>::iterator it;
        for(it = observerVector.begin(); it != observerVector.end(); ++it){
            (*it)->update(temperature, humidity, pressure);
        }
    }
    //當從氣象站得到新的數值時 通知觀察者
    void MeasurementsChanged(){
            notifyObserver();
    }
    // 獲取數據
    void SetMeasurements(float temperature, float humidity, float pressure){
            this->temperature = temperature;
            this->humidity = humidity;
            this->pressure = pressure;
            MeasurementsChanged();
    }

};

class WeatherObserver: public Display,public Observer {
private:
    float temperature;
    float humidity;
    Subject* weatherData;
public:
    WeatherObserver(){

    }
    ~WeatherObserver(){

    }
    //接受具體Subjet的註冊
    void CurrentConditionsDisplay(Subject* weatherData){
        this->weatherData = weatherData;
        weatherData->registerObserver(this);
    }
    virtual void display(){

        cout << "Current coditions: " << temperature << "F degress and " << humidity << "%% humidity" << endl;
    }
    virtual void update(float temp, float humidity, float pressure){
        this->temperature = temp;
        this->humidity = humidity;
        display();

    }

};
int main(){
    WeatherObserver wo;
    WeatherData * pwd = new WeatherData();
    wo.CurrentConditionsDisplay(pwd);
    //更新氣象數據
    pwd->SetMeasurements(20,30,10); //一旦更新數據 它的觀察者馬上作出反應執行display()
    return 0;
}

參考

博文: http://blog.csdn.net/harry_j/article/details/8435197
百度百科
其餘相關博文設計

相關文章
相關標籤/搜索