最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中觀察者模式與策略模式的實戰(zhàn)指南

 更新時間:2026年02月05日 09:50:00   作者:星河耀銀海  
本章介紹了觀察者模式和策略模式在C++中的應用,包括它們的核心設計思想、角色劃分、實現(xiàn)細節(jié)及適用場景,本文通過實例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧

18.1 本章學習目標與重點

?? 掌握觀察者模式的核心設計思想、角色劃分及 C++ 實現(xiàn)細節(jié)(同步/異步、線程安全)
?? 理解策略模式的設計原則、適用場景及與簡單工廠模式的區(qū)別
?? 能夠結合實際業(yè)務場景(如消息通知、算法切換)靈活運用兩種模式
?? 解決模式應用中的關鍵問題(如觀察者解注冊、策略動態(tài)切換、循環(huán)依賴)
重點:觀察者模式的事件分發(fā)機制、策略模式的算法封裝邏輯、兩種模式的組合使用技巧

18.2 設計模式進階認知:行為型模式的核心價值

在 C++ 開發(fā)中,行為型設計模式專注于解決“對象之間的交互方式”和“職責分配”問題,相比創(chuàng)建型模式(如工廠、單例)關注“對象創(chuàng)建”,行為型模式更側重“對象協(xié)作”。

18.2.1 為什么需要行為型設計模式?

實際開發(fā)中,我們常遇到以下交互相關的問題:

  • 一個對象狀態(tài)變化時,需要通知多個其他對象,且通知對象的數(shù)量可能動態(tài)變化(如訂單狀態(tài)更新后,需通知庫存、支付、物流系統(tǒng));
  • 一個任務有多種實現(xiàn)算法,需根據(jù)場景動態(tài)切換(如排序算法可選擇冒泡、快速、歸并排序);
  • 交互邏輯分散在多個類中,導致代碼耦合嚴重,難以維護和擴展;
  • 新增交互邏輯時,需修改現(xiàn)有代碼,違反“開放-封閉原則”。

行為型模式通過標準化的交互規(guī)則,將“交互邏輯”與“業(yè)務邏輯”分離,例如觀察者模式定義“通知-響應”規(guī)則,策略模式定義“算法封裝-動態(tài)切換”規(guī)則,從而解決上述問題。

18.2.2 行為型模式的核心設計原則

行為型模式的設計始終圍繞以下原則展開,這也是本章兩種模式的核心指導思想:

  1. 封裝變化:將易變的交互邏輯(如通知規(guī)則、算法實現(xiàn))封裝為獨立的類,避免影響其他代碼;
  2. 松耦合協(xié)作:交互的雙方(如觀察者與被觀察者、策略使用者與策略實現(xiàn))僅依賴抽象接口,不依賴具體實現(xiàn);
  3. 職責單一:每個類只負責一項核心職責(如觀察者只負責響應事件,策略類只負責實現(xiàn)算法);
  4. 開閉原則:新增交互邏輯(如新增觀察者、新增策略)時,無需修改現(xiàn)有核心代碼。

18.3 觀察者模式:事件驅動的通知機制

觀察者模式(Observer Pattern)又稱發(fā)布-訂閱模式(Publish-Subscribe Pattern),其核心思想是“定義對象間的一對多依賴關系,當一個對象狀態(tài)發(fā)生變化時,所有依賴它的對象都會收到通知并自動更新”。

18.3.1 核心角色與交互流程

1. 核心角色

  • 被觀察者(Subject):也稱主題,維護一個觀察者列表,提供注冊、解注冊觀察者的接口,以及通知所有觀察者的方法;
  • 觀察者(Observer):定義接收通知的接口,當收到被觀察者的通知時,執(zhí)行相應的更新操作;
  • 具體被觀察者(ConcreteSubject):被觀察者的具體實現(xiàn),維護自身狀態(tài),狀態(tài)變化時觸發(fā)通知;
  • 具體觀察者(ConcreteObserver):觀察者的具體實現(xiàn),實現(xiàn)更新接口,響應被觀察者的通知。

2. 交互流程

① 觀察者通過被觀察者的 RegisterObserver() 方法注冊到被觀察者中;
② 具體被觀察者的狀態(tài)發(fā)生變化;
③ 具體被觀察者調用 NotifyObservers() 方法,遍歷所有注冊的觀察者;
④ 被觀察者調用每個觀察者的 Update() 方法,傳遞狀態(tài)變化信息;
⑤ 觀察者通過 Update() 方法接收信息并執(zhí)行相應邏輯。

18.3.2 適用場景

  • 一個對象的狀態(tài)變化需要觸發(fā)多個其他對象的行為(如訂單狀態(tài)更新、股票價格變動);
  • 通知的接收者數(shù)量不固定,需要動態(tài)添加或移除(如系統(tǒng)中的消息訂閱者);
  • 觀察者與被觀察者之間無需緊密耦合,希望通過抽象接口進行通信(如跨模塊通知)。

18.3.3 基礎實現(xiàn):同步觀察者模式(C++ 示例)

以“氣象站數(shù)據(jù)監(jiān)控系統(tǒng)”為例:氣象站(被觀察者)收集溫度、濕度數(shù)據(jù),當數(shù)據(jù)更新時,需通知顯示屏、手機 App、報警器(觀察者)進行相應展示或報警。

步驟 1:定義觀察者抽象接口

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
// 觀察者抽象接口
class Observer {
public:
    // 純虛函數(shù):接收通知并更新(參數(shù):溫度、濕度)
    virtual void Update(float temperature, float humidity) = 0;
    // 虛析構函數(shù):確保子類析構時正確釋放資源
    virtual ~Observer() {}
};

步驟 2:定義被觀察者抽象接口

// 被觀察者抽象接口
class Subject {
public:
    // 注冊觀察者
    virtual void RegisterObserver(Observer* observer) = 0;
    // 解注冊觀察者
    virtual void RemoveObserver(Observer* observer) = 0;
    // 通知所有觀察者
    virtual void NotifyObservers() = 0;
    virtual ~Subject() {}
};

步驟 3:實現(xiàn)具體被觀察者(氣象站)

// 具體被觀察者:氣象站
class WeatherStation : public Subject {
private:
    vector<Observer*> observers;  // 存儲注冊的觀察者
    float temperature;            // 溫度
    float humidity;               // 濕度
    // 檢查觀察者是否已注冊(輔助函數(shù))
    bool IsObserverRegistered(Observer* observer) const {
        return find(observers.begin(), observers.end(), observer) != observers.end();
    }
public:
    // 注冊觀察者:添加到列表(避免重復注冊)
    void RegisterObserver(Observer* observer) override {
        if (observer == nullptr) {
            throw invalid_argument("觀察者不能為空指針!");
        }
        if (!IsObserverRegistered(observer)) {
            observers.push_back(observer);
            cout << "觀察者注冊成功:" << typeid(*observer).name() << endl;
        } else {
            cout << "觀察者已注冊,無需重復添加:" << typeid(*observer).name() << endl;
        }
    }
    // 解注冊觀察者:從列表中移除
    void RemoveObserver(Observer* observer) override {
        auto iter = find(observers.begin(), observers.end(), observer);
        if (iter != observers.end()) {
            observers.erase(iter);
            cout << "觀察者解注冊成功:" << typeid(*observer).name() << endl;
        } else {
            cout << "觀察者未注冊,無法解注冊:" << typeid(*observer).name() << endl;
        }
    }
    // 通知所有觀察者:遍歷列表并調用 Update 方法
    void NotifyObservers() override {
        cout << "\n氣象站數(shù)據(jù)更新,開始通知所有觀察者..." << endl;
        for (Observer* observer : observers) {
            observer->Update(temperature, humidity);
        }
    }
    // 模擬氣象數(shù)據(jù)更新(外部調用,觸發(fā)通知)
    void SetWeatherData(float temp, float humi) {
        this->temperature = temp;
        this->humidity = humi;
        cout << "\n氣象站數(shù)據(jù)更新:溫度=" << temp << "℃,濕度=" << humi << "%" << endl;
        NotifyObservers();  // 數(shù)據(jù)更新后自動通知
    }
};

步驟 4:實現(xiàn)具體觀察者(顯示屏、手機 App、報警器)

// 具體觀察者1:顯示屏(展示實時數(shù)據(jù))
class DisplayScreen : public Observer {
private:
    string screenName;  // 顯示屏名稱(如"客廳顯示屏")
public:
    DisplayScreen(const string& name) : screenName(name) {}
    void Update(float temperature, float humidity) override {
        cout << "[" << screenName << "] 實時數(shù)據(jù)展示:溫度=" << temperature << "℃,濕度=" << humidity << "%" << endl;
    }
};
// 具體觀察者2:手機 App(推送通知)
class MobileApp : public Observer {
private:
    string userName;  // 用戶名
public:
    MobileApp(const string& name) : userName(name) {}
    void Update(float temperature, float humidity) override {
        cout << "[" << userName << "的手機 App] 推送通知:當前溫度" << temperature << "℃,濕度" << humidity << "%" << endl;
    }
};
// 具體觀察者3:報警器(濕度超標時報警)
class Alarm : public Observer {
private:
    float humidityThreshold;  // 濕度閾值(超過則報警)
public:
    Alarm(float threshold) : humidityThreshold(threshold) {}
    void Update(float temperature, float humidity) override {
        if (humidity > humidityThreshold) {
            cout << "[報警器] 警告!濕度超標(當前" << humidity << "%,閾值" << humidityThreshold << "%),請及時通風!" << endl;
        } else {
            cout << "[報警器] 濕度正常(當前" << humidity << "%),無報警" << endl;
        }
    }
};

步驟 5:客戶端使用示例

int main() {
    try {
        // 1. 創(chuàng)建被觀察者:氣象站
        WeatherStation weatherStation;
        // 2. 創(chuàng)建觀察者
        Observer* livingRoomScreen = new DisplayScreen("客廳顯示屏");
        Observer* bedroomScreen = new DisplayScreen("臥室顯示屏");
        Observer* userApp = new MobileApp("張三");
        Observer* humidityAlarm = new Alarm(60.0f);  // 濕度閾值60%
        // 3. 注冊觀察者
        weatherStation.RegisterObserver(livingRoomScreen);
        weatherStation.RegisterObserver(bedroomScreen);
        weatherStation.RegisterObserver(userApp);
        weatherStation.RegisterObserver(humidityAlarm);
        // 4. 模擬數(shù)據(jù)更新(觸發(fā)第一次通知)
        weatherStation.SetWeatherData(25.5f, 55.0f);
        // 5. 解注冊臥室顯示屏(不再接收通知)
        weatherStation.RemoveObserver(bedroomScreen);
        cout << "\n--- 解注冊臥室顯示屏后 ---" << endl;
        // 6. 模擬數(shù)據(jù)更新(觸發(fā)第二次通知,臥室顯示屏不再接收)
        weatherStation.SetWeatherData(26.8f, 62.0f);  // 濕度超標,報警器會報警
        // 7. 釋放資源
        delete livingRoomScreen;
        delete bedroomScreen;
        delete userApp;
        delete humidityAlarm;
    } catch (const exception& e) {
        cout << "錯誤:" << e.what() << endl;
    }
    return 0;
}

運行結果

觀察者注冊成功:class DisplayScreen
觀察者注冊成功:class DisplayScreen
觀察者注冊成功:class MobileApp
觀察者注冊成功:class Alarm

氣象站數(shù)據(jù)更新:溫度=25.5℃,濕度=55.0%

氣象站數(shù)據(jù)更新,開始通知所有觀察者...
[客廳顯示屏] 實時數(shù)據(jù)展示:溫度=25.5℃,濕度=55.0%
[臥室顯示屏] 實時數(shù)據(jù)展示:溫度=25.5℃,濕度=55.0%
[張三的手機 App] 推送通知:當前溫度25.5℃,濕度55.0%
[報警器] 濕度正常(當前55.0%),無報警

觀察者解注冊成功:class DisplayScreen

--- 解注冊臥室顯示屏后 ---

氣象站數(shù)據(jù)更新:溫度=26.8℃,濕度=62.0%

氣象站數(shù)據(jù)更新,開始通知所有觀察者...
[客廳顯示屏] 實時數(shù)據(jù)展示:溫度=26.8℃,濕度=62.0%
[張三的手機 App] 推送通知:當前溫度26.8℃,濕度62.0%
[報警器] 警告!濕度超標(當前62.0%,閾值60.0%),請及時通風!

18.3.4 進階優(yōu)化:線程安全與異步通知

基礎實現(xiàn)是同步通知(被觀察者在主線程中依次調用觀察者的 Update() 方法),存在兩個問題:

  1. 線程安全風險:若多個線程同時修改被觀察者狀態(tài)或注冊/解注冊觀察者,可能導致列表遍歷異常;
  2. 性能瓶頸:若某個觀察者的 Update() 方法執(zhí)行耗時較長,會阻塞其他觀察者的通知。

優(yōu)化方案 1:線程安全的同步通知(加鎖保護)

使用 std::mutex 保護觀察者列表的讀寫操作,確保多線程環(huán)境下的安全性:

#include <mutex>
// 線程安全的氣象站(繼承自原 WeatherStation,重寫核心方法)
class ThreadSafeWeatherStation : public Subject {
private:
    vector<Observer*> observers;
    float temperature;
    float humidity;
    mutex mtx;  // 互斥鎖,保護觀察者列表
public:
    void RegisterObserver(Observer* observer) override {
        if (observer == nullptr) {
            throw invalid_argument("觀察者不能為空指針!");
        }
        lock_guard<mutex> lock(mtx);  // 自動加鎖/解鎖
        auto iter = find(observers.begin(), observers.end(), observer);
        if (iter == observers.end()) {
            observers.push_back(observer);
            cout << "線程安全注冊:" << typeid(*observer).name() << endl;
        }
    }
    void RemoveObserver(Observer* observer) override {
        lock_guard<mutex> lock(mtx);
        auto iter = find(observers.begin(), observers.end(), observer);
        if (iter != observers.end()) {
            observers.erase(iter);
            cout << "線程安全解注冊:" << typeid(*observer).name() << endl;
        }
    }
    void NotifyObservers() override {
        lock_guard<mutex> lock(mtx);
        cout << "\n線程安全通知所有觀察者..." << endl;
        // 拷貝一份觀察者列表,避免遍歷過程中列表被修改(如解注冊)
        vector<Observer*> tempObservers = observers;
        lock.unlock();  // 提前解鎖,減少阻塞時間
        for (Observer* observer : tempObservers) {
            observer->Update(temperature, humidity);
        }
    }
    void SetWeatherData(float temp, float humi) {
        lock_guard<mutex> lock(mtx);
        this->temperature = temp;
        this->humidity = humi;
        cout << "\n線程安全氣象站數(shù)據(jù):溫度=" << temp << "℃,濕度=" << humi << "%" << endl;
        lock.unlock();
        NotifyObservers();  // 通知操作在解鎖后執(zhí)行,避免阻塞寫操作
    }
};

優(yōu)化方案 2:異步通知(使用線程池)

通過線程池異步執(zhí)行觀察者的 Update() 方法,避免單個觀察者阻塞整個通知流程:

#include <thread>
#include <queue>
#include <condition_variable>
// 簡單線程池(用于異步執(zhí)行任務)
class ThreadPool {
private:
    vector<thread> workers;       // 工作線程
    queue<function<void()>> tasks;// 任務隊列
    mutex mtx;                    // 保護任務隊列
    condition_variable cv;        // 條件變量,喚醒線程
    bool stop;                    // 線程池停止標志
public:
    // 構造函數(shù):創(chuàng)建n個工作線程
    ThreadPool(size_t n) : stop(false) {
        for (size_t i = 0; i < n; ++i) {
            workers.emplace_back([this]() {
                while (true) {
                    function<void()> task;
                    {
                        unique_lock<mutex> lock(this->mtx);
                        // 等待任務或停止信號
                        this->cv.wait(lock, [this]() {
                            return this->stop || !this->tasks.empty();
                        });
                        // 線程池停止且任務隊列為空,退出線程
                        if (this->stop && this->tasks.empty()) {
                            return;
                        }
                        // 取出任務
                        task = move(this->tasks.front());
                        this->tasks.pop();
                    }
                    // 執(zhí)行任務
                    task();
                }
            });
        }
    }
    // 析構函數(shù):停止線程池
    ~ThreadPool() {
        {
            unique_lock<mutex> lock(mtx);
            stop = true;
        }
        cv.notify_all();  // 喚醒所有工作線程
        for (thread& worker : workers) {
            worker.join();  // 等待所有線程完成
        }
    }
    // 添加任務到線程池
    template<typename F>
    void Enqueue(F&& f) {
        {
            unique_lock<mutex> lock(mtx);
            if (stop) {
                throw runtime_error("線程池已停止,無法添加任務!");
            }
            tasks.emplace(forward<F>(f));
        }
        cv.notify_one();  // 喚醒一個工作線程
    }
};
// 異步通知的氣象站
class AsyncWeatherStation : public Subject {
private:
    vector<Observer*> observers;
    float temperature;
    float humidity;
    mutex mtx;
    ThreadPool pool;  // 線程池(2個工作線程)
public:
    AsyncWeatherStation() : pool(2) {}
    void RegisterObserver(Observer* observer) override {
        lock_guard<mutex> lock(mtx);
        if (observer && find(observers.begin(), observers.end(), observer) == observers.end()) {
            observers.push_back(observer);
        }
    }
    void RemoveObserver(Observer* observer) override {
        lock_guard<mutex> lock(mtx);
        auto iter = find(observers.begin(), observers.end(), observer);
        if (iter != observers.end()) {
            observers.erase(iter);
        }
    }
    void NotifyObservers() override {
        lock_guard<mutex> lock(mtx);
        vector<Observer*> tempObservers = observers;
        float temp = temperature;
        float humi = humidity;
        // 異步執(zhí)行每個觀察者的 Update 方法
        for (Observer* observer : tempObservers) {
            pool.Enqueue([observer, temp, humi]() {
                observer->Update(temp, humi);
            });
        }
    }
    void SetWeatherData(float temp, float humi) {
        lock_guard<mutex> lock(mtx);
        this->temperature = temp;
        this->humidity = humi;
        cout << "\n異步氣象站數(shù)據(jù)更新:溫度=" << temp << "℃,濕度=" << humi << "%" << endl;
        lock.unlock();
        NotifyObservers();
    }
};

異步通知測試代碼

// 模擬耗時的觀察者(如網(wǎng)絡請求)
class SlowObserver : public Observer {
public:
    void Update(float temperature, float humidity) override {
        cout << "[耗時觀察者] 開始處理數(shù)據(jù)(模擬網(wǎng)絡請求)..." << endl;
        this_thread::sleep_for(chrono::seconds(2));  // 模擬2秒耗時
        cout << "[耗時觀察者] 數(shù)據(jù)處理完成:溫度=" << temperature << "℃" << endl;
    }
};
int main() {
    AsyncWeatherStation weatherStation;
    Observer* fastObserver = new DisplayScreen("快速顯示屏");
    Observer* slowObserver = new SlowObserver();
    weatherStation.RegisterObserver(fastObserver);
    weatherStation.RegisterObserver(slowObserver);
    weatherStation.SetWeatherData(24.0f, 58.0f);
    cout << "主線程繼續(xù)執(zhí)行其他任務..." << endl;
    // 等待異步任務完成(實際項目中無需手動等待,線程池會后臺處理)
    this_thread::sleep_for(chrono::seconds(3));
    delete fastObserver;
    delete slowObserver;
    return 0;
}

異步通知運行結果

異步氣象站數(shù)據(jù)更新:溫度=24.0℃,濕度=58.0%
主線程繼續(xù)執(zhí)行其他任務...
[快速顯示屏] 實時數(shù)據(jù)展示:溫度=24.0℃,濕度=58.0%
[耗時觀察者] 開始處理數(shù)據(jù)(模擬網(wǎng)絡請求)...
[耗時觀察者] 數(shù)據(jù)處理完成:溫度=24.0℃

18.3.5 觀察者模式的優(yōu)缺點與避坑指南

優(yōu)點

? 解耦被觀察者與觀察者:兩者僅依賴抽象接口,無需知道對方的具體實現(xiàn);
? 動態(tài)擴展:可隨時添加/移除觀察者,無需修改被觀察者代碼,符合“開放-封閉原則”;
? 廣播通知:被觀察者狀態(tài)變化時,自動通知所有注冊的觀察者,無需手動調用。

缺點

?? 通知順序不確定:同步通知時,觀察者的更新順序與注冊順序一致,但異步通知時順序不可控;
?? 循環(huán)依賴風險:若觀察者與被觀察者相互引用,可能導致內存泄漏(需使用弱指針 weak_ptr 解決);
?? 性能開銷:若觀察者數(shù)量過多或 Update() 方法耗時,同步通知會導致性能瓶頸(需異步優(yōu)化)。

避坑指南

?? 避免觀察者列表遍歷期間修改列表:注冊/解注冊時需加鎖,或拷貝列表后遍歷(如線程安全實現(xiàn));
?? 處理觀察者空指針:注冊時校驗觀察者指針非空,避免通知時崩潰;
?? 內存管理:被觀察者不負責銷毀觀察者,需由客戶端統(tǒng)一管理,或使用智能指針(shared_ptr);
?? 避免過度通知:僅在狀態(tài)真正變化時觸發(fā)通知,避免無效更新(如氣象站數(shù)據(jù)未變化時不通知)。

18.4 策略模式:算法的封裝與動態(tài)切換

策略模式(Strategy Pattern)的核心思想是“定義一系列算法,將每個算法封裝起來,并且使它們可以相互替換,讓算法的變化獨立于使用算法的客戶”。

18.4.1 核心角色與設計邏輯

1. 核心角色

  • 策略抽象(Strategy):定義算法的抽象接口,所有具體策略都需實現(xiàn)該接口;
  • 具體策略(ConcreteStrategy):算法的具體實現(xiàn),實現(xiàn)策略抽象接口;
  • 上下文(Context):使用策略的角色,持有一個策略對象的引用,提供切換策略的接口,負責調用策略執(zhí)行算法。

2. 設計邏輯

將易變的算法(如排序算法、支付方式、壓縮算法)封裝為獨立的策略類,上下文通過依賴注入或動態(tài)設置的方式使用策略,從而實現(xiàn)“算法切換無需修改上下文代碼”。

18.4.2 適用場景

  • 一個任務有多種實現(xiàn)方式(算法),且需根據(jù)場景動態(tài)切換(如電商支付支持微信、支付寶、銀行卡支付);
  • 算法細節(jié)復雜,且需要隱藏(如加密算法的實現(xiàn)細節(jié)不希望暴露給客戶端);
  • 避免使用多重 if-elseswitch 判斷選擇算法(如不同會員等級對應不同折扣策略);
  • 算法需要靈活擴展,新增算法時無需修改現(xiàn)有代碼。

18.4.3 基礎實現(xiàn):電商折扣策略系統(tǒng)(C++ 示例)

以“電商平臺折扣系統(tǒng)”為例:不同用戶(普通用戶、VIP用戶、超級VIP用戶)對應不同折扣策略,且平臺可能新增“節(jié)日折扣”“優(yōu)惠券折扣”等策略,使用策略模式可靈活擴展。

步驟 1:定義策略抽象接口(折扣算法)

#include <iostream>
#include <string>
#include <memory>
using namespace std;
// 策略抽象:折扣策略
class DiscountStrategy {
public:
    // 純虛函數(shù):計算折扣后的價格(參數(shù):原價)
    virtual float CalculateDiscount(float originalPrice) const = 0;
    // 獲取策略名稱(用于日志輸出)
    virtual string GetStrategyName() const = 0;
    virtual ~DiscountStrategy() {}
};

步驟 2:實現(xiàn)具體策略(不同折扣算法)

// 具體策略1:普通用戶策略(無折扣)
class NormalUserStrategy : public DiscountStrategy {
public:
    float CalculateDiscount(float originalPrice) const override {
        return originalPrice;  // 無折扣,原價返回
    }
    string GetStrategyName() const override {
        return "普通用戶無折扣";
    }
};
// 具體策略2:VIP用戶策略(9折)
class VIPUserStrategy : public DiscountStrategy {
public:
    float CalculateDiscount(float originalPrice) const override {
        return originalPrice * 0.9f;  // 9折
    }
    string GetStrategyName() const override {
        return "VIP用戶9折";
    }
};
// 具體策略3:超級VIP用戶策略(8折+滿1000減200)
class SuperVIPUserStrategy : public DiscountStrategy {
public:
    float CalculateDiscount(float originalPrice) const override {
        float discountPrice = originalPrice * 0.8f;  // 先打8折
        if (discountPrice >= 1000) {
            discountPrice -= 200;  // 滿1000減200
        }
        return discountPrice;
    }
    string GetStrategyName() const override {
        return "超級VIP用戶8折+滿1000減200";
    }
};
// 具體策略4:節(jié)日折扣策略(7折,限節(jié)日使用)
class FestivalDiscountStrategy : public DiscountStrategy {
public:
    float CalculateDiscount(float originalPrice) const override {
        return originalPrice * 0.7f;  // 7折
    }
    string GetStrategyName() const override {
        return "節(jié)日折扣7折";
    }
};

步驟 3:實現(xiàn)上下文(訂單結算系統(tǒng))

// 上下文:訂單結算系統(tǒng)
class OrderSettlement {
private:
    // 持有策略對象(使用智能指針,自動管理內存)
    shared_ptr<DiscountStrategy> strategy;
public:
    // 構造函數(shù):初始化策略(默認普通用戶策略)
    OrderSettlement() : strategy(make_shared<NormalUserStrategy>()) {}
    // 動態(tài)切換策略(核心方法:支持運行時更換策略)
    void SetDiscountStrategy(shared_ptr<DiscountStrategy> newStrategy) {
        if (newStrategy == nullptr) {
            throw invalid_argument("策略不能為空!");
        }
        strategy = newStrategy;
        cout << "折扣策略切換為:" << strategy->GetStrategyName() << endl;
    }
    // 結算:調用當前策略計算最終價格
    float Settle(float originalPrice) const {
        if (originalPrice < 0) {
            throw invalid_argument("商品原價不能為負數(shù)!");
        }
        float finalPrice = strategy->CalculateDiscount(originalPrice);
        cout << "當前策略:" << strategy->GetStrategyName() << endl;
        cout << "商品原價:" << originalPrice << "元,最終價格:" << finalPrice << "元" << endl;
        return finalPrice;
    }
};

步驟 4:客戶端使用示例

int main() {
    try {
        // 1. 創(chuàng)建上下文:訂單結算系統(tǒng)
        OrderSettlement settlement;
        // 2. 普通用戶結算(默認策略)
        cout << "=== 普通用戶購買商品(原價500元)===" << endl;
        settlement.Settle(500.0f);
        // 3. 切換為VIP用戶策略
        cout << "\n=== VIP用戶購買商品(原價800元)===" << endl;
        settlement.SetDiscountStrategy(make_shared<VIPUserStrategy>());
        settlement.Settle(800.0f);
        // 4. 切換為超級VIP用戶策略
        cout << "\n=== 超級VIP用戶購買商品(原價1500元)===" << endl;
        settlement.SetDiscountStrategy(make_shared<SuperVIPUserStrategy>());
        settlement.Settle(1500.0f);
        // 5. 切換為節(jié)日折扣策略
        cout << "\n=== 節(jié)日期間購買商品(原價2000元)===" << endl;
        settlement.SetDiscountStrategy(make_shared<FestivalDiscountStrategy>());
        settlement.Settle(2000.0f);
        // 6. 新增策略:無需修改結算系統(tǒng)代碼,直接使用
        cout << "\n=== 新增優(yōu)惠券策略(假設已實現(xiàn))===" << endl;
        // 假設新增 CouponDiscountStrategy,直接通過 SetDiscountStrategy 切換
        // settlement.SetDiscountStrategy(make_shared<CouponDiscountStrategy>());
        // settlement.Settle(1000.0f);
    } catch (const exception& e) {
        cout << "結算失?。? << e.what() << endl;
    }
    return 0;
}

運行結果

=== 普通用戶購買商品(原價500元)===
當前策略:普通用戶無折扣
商品原價:500元,最終價格:500元

=== VIP用戶購買商品(原價800元)===
折扣策略切換為:VIP用戶9折
當前策略:VIP用戶9折
商品原價:800元,最終價格:720元

=== 超級VIP用戶購買商品(原價1500元)===
折扣策略切換為:超級VIP用戶8折+滿1000減200
當前策略:超級VIP用戶8折+滿1000減200
商品原價:1500元,最終價格:1000元

=== 節(jié)日期間購買商品(原價2000元)===
折扣策略切換為:節(jié)日折扣7折
當前策略:節(jié)日折扣7折
商品原價:2000元,最終價格:1400元

=== 新增優(yōu)惠券策略(假設已實現(xiàn))===

18.4.4 策略模式與簡單工廠模式的區(qū)別

很多開發(fā)者會混淆策略模式與簡單工廠模式,兩者的核心區(qū)別如下:

對比維度策略模式簡單工廠模式
核心目的封裝算法,支持動態(tài)切換封裝對象創(chuàng)建,統(tǒng)一創(chuàng)建邏輯
關注點算法的“使用”與“切換”對象的“創(chuàng)建”
交互方式上下文持有策略對象,主動調用策略方法客戶端調用工廠創(chuàng)建對象,自行使用
擴展性新增算法只需新增策略類,無侵入新增產品需修改工廠類(違反開閉原則)
適用場景算法多變、需動態(tài)切換產品類型少、創(chuàng)建邏輯簡單

?? 實戰(zhàn)技巧:策略模式可與簡單工廠模式結合使用!例如,在上下文內部通過簡單工廠根據(jù)條件自動選擇策略,無需客戶端手動切換:

// 結合簡單工廠的上下文
class FactoryStrategySettlement {
private:
    shared_ptr<DiscountStrategy> strategy;
    // 簡單工廠:根據(jù)用戶類型創(chuàng)建策略
    shared_ptr<DiscountStrategy> CreateStrategy(const string& userType) {
        if (userType == "normal") {
            return make_shared<NormalUserStrategy>();
        } else if (userType == "vip") {
            return make_shared<VIPUserStrategy>();
        } else if (userType == "super_vip") {
            return make_shared<SuperVIPUserStrategy>();
        } else {
            throw invalid_argument("不支持的用戶類型:" + userType);
        }
    }
public:
    // 根據(jù)用戶類型自動選擇策略
    FactoryStrategySettlement(const string& userType) {
        strategy = CreateStrategy(userType);
    }
    float Settle(float originalPrice) const {
        float finalPrice = strategy->CalculateDiscount(originalPrice);
        cout << "用戶類型對應策略:" << strategy->GetStrategyName() << endl;
        cout << "原價:" << originalPrice << "元,最終價:" << finalPrice << "元" << endl;
        return finalPrice;
    }
};
// 客戶端使用
int main() {
    FactoryStrategySettlement vipSettlement("vip");
    vipSettlement.Settle(1000.0f);  // 自動使用VIP策略
    return 0;
}

18.4.5 策略模式的優(yōu)缺點與避坑指南

優(yōu)點

? 算法封裝清晰:每個策略類只負責一種算法,職責單一,便于維護;
? 支持動態(tài)切換:上下文可在運行時切換策略,無需重啟程序;
? 符合開閉原則:新增算法只需新增策略類,無需修改上下文或其他策略代碼;
? 避免多重條件判斷:替代 if-else/switch,代碼更簡潔、易擴展。

缺點

?? 類數(shù)量增加:每新增一種算法,需新增一個策略類,若算法過多會導致類數(shù)量爆炸;
?? 客戶端需了解策略:客戶端需知道所有策略的存在,才能選擇合適的策略(可通過工廠模式優(yōu)化);
?? 策略間無依賴:若策略之間需要共享數(shù)據(jù),需通過上下文傳遞,增加復雜度。

避坑指南

?? 策略粒度適中:避免將過于簡單的算法封裝為策略(如僅一行代碼的計算),導致過度設計;
?? 使用智能指針管理策略:避免策略對象內存泄漏,簡化客戶端內存管理;
?? 策略不可變:設計策略類時,盡量使其為無狀態(tài)類(不存儲動態(tài)數(shù)據(jù)),確保線程安全;
?? 復雜策略組合:若需組合多種策略(如“折扣+優(yōu)惠券”),可結合裝飾者模式(后續(xù)章節(jié)講解)。

18.5 實戰(zhàn)案例:結合觀察者模式與策略模式開發(fā)智能物流調度系統(tǒng)

18.5.1 需求分析

開發(fā)一個智能物流調度系統(tǒng),核心需求如下:

  1. 訂單狀態(tài)變化時(如“已支付”“已發(fā)貨”“已簽收”),需通知客戶 App、商家后臺、物流系統(tǒng);
  2. 調度算法可動態(tài)切換:根據(jù)訂單類型(普通訂單、加急訂單、大件訂單)選擇不同的調度策略(如普通調度、優(yōu)先調度、大件專用調度);
  3. 支持新增訂單狀態(tài)通知對象(如未來新增“保險公司”通知);
  4. 支持新增調度策略(如未來新增“冷鏈物流調度”);
  5. 多線程環(huán)境下安全運行(如同時處理多個訂單狀態(tài)更新)。

18.5.2 設計思路

  • 觀察者模式:處理訂單狀態(tài)通知,訂單(被觀察者)狀態(tài)變化時,通知客戶 App、商家后臺等觀察者;
  • 策略模式:處理調度算法,調度系統(tǒng)(上下文)根據(jù)訂單類型選擇對應的調度策略;
  • 組合設計:訂單狀態(tài)更新后,觸發(fā)調度系統(tǒng)執(zhí)行調度算法,調度結果通過觀察者模式通知相關方。

18.5.3 完整實現(xiàn)代碼

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <mutex>
#include <memory>
#include <thread>
using namespace std;
// -------------------------- 部分1:觀察者模式(訂單狀態(tài)通知) --------------------------
// 觀察者抽象:接收訂單狀態(tài)通知
class OrderStatusObserver {
public:
    virtual void OnStatusChanged(const string& orderId, const string& status) = 0;
    virtual string GetObserverName() const = 0;
    virtual ~OrderStatusObserver() {}
};
// 具體觀察者1:客戶 App
class CustomerAppObserver : public OrderStatusObserver {
public:
    void OnStatusChanged(const string& orderId, const string& status) override {
        cout << "[客戶 App] 訂單" << orderId << "狀態(tài)更新為:" << status << ",已推送通知給客戶" << endl;
    }
    string GetObserverName() const override {
        return "客戶 App";
    }
};
// 具體觀察者2:商家后臺
class MerchantBackendObserver : public OrderStatusObserver {
public:
    void OnStatusChanged(const string& orderId, const string& status) override {
        cout << "[商家后臺] 訂單" << orderId << "狀態(tài)更新為:" << status << ",已同步至商家管理系統(tǒng)" << endl;
    }
    string GetObserverName() const override {
        return "商家后臺";
    }
};
// 具體觀察者3:物流系統(tǒng)
class LogisticsSystemObserver : public OrderStatusObserver {
public:
    void OnStatusChanged(const string& orderId, const string& status) override {
        cout << "[物流系統(tǒng)] 訂單" << orderId << "狀態(tài)更新為:" << status << ",已觸發(fā)物流調度" << endl;
    }
    string GetObserverName() const override {
        return "物流系統(tǒng)";
    }
};
// 被觀察者:訂單
class Order : public Subject {
private:
    string orderId;
    string status;  // 訂單狀態(tài):"unpaid"(未支付)、"paid"(已支付)、"shipped"(已發(fā)貨)、"received"(已簽收)
    vector<OrderStatusObserver*> observers;
    mutex mtx;
public:
    Order(const string& id) : orderId(id), status("unpaid") {}
    // 注冊觀察者(重寫 Subject 接口)
    void RegisterObserver(Observer* observer) override {
        if (observer == nullptr) return;
        OrderStatusObserver* statusObserver = dynamic_cast<OrderStatusObserver*>(observer);
        if (statusObserver == nullptr) {
            throw invalid_argument("觀察者類型不匹配!");
        }
        lock_guard<mutex> lock(mtx);
        auto iter = find(observers.begin(), observers.end(), statusObserver);
        if (iter == observers.end()) {
            observers.push_back(statusObserver);
            cout << "訂單" << orderId << "注冊觀察者:" << statusObserver->GetObserverName() << endl;
        }
    }
    // 解注冊觀察者(重寫 Subject 接口)
    void RemoveObserver(Observer* observer) override {
        OrderStatusObserver* statusObserver = dynamic_cast<OrderStatusObserver*>(observer);
        if (statusObserver == nullptr) return;
        lock_guard<mutex> lock(mtx);
        auto iter = find(observers.begin(), observers.end(), statusObserver);
        if (iter != observers.end()) {
            observers.erase(iter);
            cout << "訂單" << orderId << "解注冊觀察者:" << statusObserver->GetObserverName() << endl;
        }
    }
    // 通知觀察者(重寫 Subject 接口)
    void NotifyObservers() override {
        lock_guard<mutex> lock(mtx);
        vector<OrderStatusObserver*> tempObservers = observers;
        string tempOrderId = orderId;
        string tempStatus = status;
        // 異步通知(避免阻塞訂單狀態(tài)更新)
        thread([tempObservers, tempOrderId, tempStatus]() {
            for (OrderStatusObserver* observer : tempObservers) {
                observer->OnStatusChanged(tempOrderId, tempStatus);
            }
        }).detach();
    }
    // 更新訂單狀態(tài)(觸發(fā)通知)
    void UpdateStatus(const string& newStatus) {
        if (newStatus != "unpaid" && newStatus != "paid" && newStatus != "shipped" && newStatus != "received") {
            throw invalid_argument("無效的訂單狀態(tài):" + newStatus);
        }
        lock_guard<mutex> lock(mtx);
        if (this->status == newStatus) {
            cout << "訂單" << orderId << "狀態(tài)未變化(當前:" << newStatus << ")" << endl;
            return;
        }
        this->status = newStatus;
        cout << "\n訂單" << orderId << "狀態(tài)更新為:" << newStatus << endl;
        NotifyObservers();
    }
    // 獲取訂單狀態(tài)
    string GetStatus() const {
        lock_guard<mutex> lock(mtx);
        return status;
    }
    // 獲取訂單ID
    string GetOrderId() const {
        return orderId;
    }
};
// -------------------------- 部分2:策略模式(物流調度算法) --------------------------
// 策略抽象:調度策略
class DispatchStrategy {
public:
    virtual string Dispatch(const string& orderId, const string& orderType) const = 0;
    virtual string GetStrategyName() const = 0;
    virtual ~DispatchStrategy() {}
};
// 具體策略1:普通調度(適用于普通訂單)
class NormalDispatchStrategy : public DispatchStrategy {
public:
    string Dispatch(const string& orderId, const string& orderType) const override {
        string result = "訂單" + orderId + "(" + orderType + ")使用普通調度:分配常規(guī)物流車輛,預計3-5天送達";
        cout << result << endl;
        return result;
    }
    string GetStrategyName() const override {
        return "普通調度策略";
    }
};
// 具體策略2:優(yōu)先調度(適用于加急訂單)
class PriorityDispatchStrategy : public DispatchStrategy {
public:
    string Dispatch(const string& orderId, const string& orderType) const override {
        string result = "訂單" + orderId + "(" + orderType + ")使用優(yōu)先調度:分配加急物流車輛,預計1-2天送達";
        cout << result << endl;
        return result;
    }
    string GetStrategyName() const override {
        return "優(yōu)先調度策略";
    }
};
// 具體策略3:大件調度(適用于大件訂單)
class LargeItemDispatchStrategy : public DispatchStrategy {
public:
    string Dispatch(const string& orderId, const string& orderType) const override {
        string result = "訂單" + orderId + "(" + orderType + ")使用大件調度:分配專用大件物流車輛,預計2-4天送達";
        cout << result << endl;
        return result;
    }
    string GetStrategyName() const override {
        return "大件調度策略";
    }
};
// 上下文:物流調度系統(tǒng)
class LogisticsDispatchSystem {
private:
    mutex mtx;
    // 策略映射:訂單類型 -> 策略(支持動態(tài)配置)
    map<string, shared_ptr<DispatchStrategy>> strategyMap;
public:
    // 初始化默認策略
    LogisticsDispatchSystem() {
        strategyMap["normal"] = make_shared<NormalDispatchStrategy>();       // 普通訂單
        strategyMap["express"] = make_shared<PriorityDispatchStrategy>();    // 加急訂單
        strategyMap["large"] = make_shared<LargeItemDispatchStrategy>();     // 大件訂單
    }
    // 注冊新策略(支持動態(tài)新增)
    void RegisterStrategy(const string& orderType, shared_ptr<DispatchStrategy> strategy) {
        if (orderType.empty() || strategy == nullptr) {
            throw invalid_argument("訂單類型或策略不能為空!");
        }
        lock_guard<mutex> lock(mtx);
        strategyMap[orderType] = strategy;
        cout << "注冊新調度策略:訂單類型=" << orderType << ",策略=" << strategy->GetStrategyName() << endl;
    }
    // 執(zhí)行調度(根據(jù)訂單類型選擇策略)
    string DispatchOrder(const string& orderId, const string& orderType) {
        lock_guard<mutex> lock(mtx);
        auto iter = strategyMap.find(orderType);
        if (iter == strategyMap.end()) {
            throw invalid_argument("不支持的訂單類型:" + orderType);
        }
        return iter->second->Dispatch(orderId, orderType);
    }
};
// -------------------------- 部分3:系統(tǒng)整合與客戶端測試 --------------------------
// 系統(tǒng)整合:訂單狀態(tài)更新后觸發(fā)調度
void OnOrderStatusUpdated(const shared_ptr<Order>& order, const shared_ptr<LogisticsDispatchSystem>& dispatchSystem, const string& orderType) {
    string status = order->GetStatus();
    if (status == "paid") {  // 訂單已支付,觸發(fā)調度
        cout << "\n--- 訂單" << order->GetOrderId() << "已支付,開始物流調度 ---" << endl;
        dispatchSystem->DispatchOrder(order->GetOrderId(), orderType);
    }
}
int main() {
    try {
        // 1. 創(chuàng)建物流調度系統(tǒng)
        auto dispatchSystem = make_shared<LogisticsDispatchSystem>();
        // 2. 創(chuàng)建觀察者
        auto customerApp = make_shared<CustomerAppObserver>();
        auto merchantBackend = make_shared<MerchantBackendObserver>();
        auto logisticsSystem = make_shared<LogisticsSystemObserver>();
        // 3. 創(chuàng)建訂單(普通訂單、加急訂單)
        auto normalOrder = make_shared<Order>("ORD20240501001");  // 普通訂單
        auto expressOrder = make_shared<Order>("ORD20240501002"); // 加急訂單
        // 4. 為訂單注冊觀察者
        normalOrder->RegisterObserver(customerApp.get());
        normalOrder->RegisterObserver(merchantBackend.get());
        normalOrder->RegisterObserver(logisticsSystem.get());
        expressOrder->RegisterObserver(customerApp.get());
        expressOrder->RegisterObserver(merchantBackend.get());
        expressOrder->RegisterObserver(logisticsSystem.get());
        // 5. 模擬普通訂單流程:未支付 -> 已支付(觸發(fā)調度)-> 已發(fā)貨 -> 已簽收
        cout << "=== 普通訂單流程 ===" << endl;
        normalOrder->UpdateStatus("paid");  // 已支付,觸發(fā)調度
        this_thread::sleep_for(chrono::seconds(1));  // 等待異步通知完成
        OnOrderStatusUpdated(normalOrder, dispatchSystem, "normal");
        normalOrder->UpdateStatus("shipped");  // 已發(fā)貨
        this_thread::sleep_for(chrono::seconds(1));
        normalOrder->UpdateStatus("received");  // 已簽收
        this_thread::sleep_for(chrono::seconds(1));
        // 6. 模擬加急訂單流程
        cout << "\n=== 加急訂單流程 ===" << endl;
        expressOrder->UpdateStatus("paid");  // 已支付,觸發(fā)調度
        this_thread::sleep_for(chrono::seconds(1));
        OnOrderStatusUpdated(expressOrder, dispatchSystem, "express");
        // 7. 新增冷鏈物流策略(擴展功能)
        class ColdChainDispatchStrategy : public DispatchStrategy {
        public:
            string Dispatch(const string& orderId, const string& orderType) const override {
                return "訂單" + orderId + "(" + orderType + ")使用冷鏈調度:分配冷藏物流車輛,預計1-2天送達";
            }
            string GetStrategyName() const override { return "冷鏈調度策略"; }
        };
        dispatchSystem->RegisterStrategy("cold_chain", make_shared<ColdChainDispatchStrategy>());
        // 8. 測試新增的冷鏈訂單
        auto coldChainOrder = make_shared<Order>("ORD20240501003");
        coldChainOrder->RegisterObserver(customerApp.get());
        cout << "\n=== 冷鏈訂單流程 ===" << endl;
        coldChainOrder->UpdateStatus("paid");
        this_thread::sleep_for(chrono::seconds(1));
        OnOrderStatusUpdated(coldChainOrder, dispatchSystem, "cold_chain");
    } catch (const exception& e) {
        cout << "系統(tǒng)錯誤:" << e.what() << endl;
    }
    return 0;
}

18.5.4 代碼說明與運行效果

核心設計亮點

  • 觀察者模式負責“狀態(tài)通知”:訂單狀態(tài)變化時,異步通知客戶 App、商家后臺等,解耦訂單與通知接收方;
  • 策略模式負責“算法調度”:根據(jù)訂單類型動態(tài)選擇調度策略,支持新增策略(如冷鏈調度)無侵入擴展;
  • 組合使用:訂單“已支付”狀態(tài)觸發(fā)物流調度,實現(xiàn)兩種模式的聯(lián)動,滿足復雜業(yè)務流程;
  • 線程安全:觀察者注冊/解注冊、訂單狀態(tài)更新、策略調度均加鎖保護,支持多線程并發(fā)處理。

運行結果(關鍵片段)

訂單ORD20240501001注冊觀察者:客戶 App
訂單ORD20240501001注冊觀察者:商家后臺
訂單ORD20240501001注冊觀察者:物流系統(tǒng)
...
=== 普通訂單流程 ===

訂單ORD20240501001狀態(tài)更新為:paid
[客戶 App] 訂單ORD20240501001狀態(tài)更新為:paid,已推送通知給客戶
[商家后臺] 訂單ORD20240501001狀態(tài)更新為:paid,已同步至商家管理系統(tǒng)
[物流系統(tǒng)] 訂單ORD20240501001狀態(tài)更新為:paid,已觸發(fā)物流調度

--- 訂單ORD20240501001已支付,開始物流調度 ---
訂單ORD20240501001(normal)使用普通調度:分配常規(guī)物流車輛,預計3-5天送達
...
=== 冷鏈訂單流程 ===
注冊新調度策略:訂單類型=cold_chain,策略=冷鏈調度策略

訂單ORD20240501003狀態(tài)更新為:paid
[客戶 App] 訂單ORD20240501003狀態(tài)更新為:paid,已推送通知給客戶

--- 訂單ORD20240501003已支付,開始物流調度 ---
訂單ORD20240501003(cold_chain)使用冷鏈調度:分配冷藏物流車輛,預計1-2天送達

18.6 本章總結

本章重點講解了 C++ 開發(fā)中常用的兩種行為型設計模式:觀察者模式和策略模式,核心要點總結如下:

  • 觀察者模式:
    • 核心價值:實現(xiàn)“一對多”的通知機制,解耦被觀察者與觀察者;
    • 關鍵實現(xiàn):抽象觀察者接口、被觀察者維護觀察者列表、通知機制(同步/異步);
    • 進階優(yōu)化:線程安全(加鎖)、異步通知(線程池)、避免循環(huán)依賴(弱指針);
    • 適用場景:狀態(tài)變化通知、消息訂閱、跨模塊通信。
  • 策略模式:
    • 核心價值:封裝算法,支持動態(tài)切換,替代多重條件判斷;
    • 關鍵實現(xiàn):策略抽象接口、具體策略類、上下文持有并調用策略;
    • 與工廠模式區(qū)別:策略模式關注“算法使用與切換”,工廠模式關注“對象創(chuàng)建”;
    • 適用場景:算法多變、動態(tài)切換邏輯(如支付方式、調度算法、折扣策略)。
  • 模式組合技巧:
    • 觀察者模式 + 策略模式:狀態(tài)變化觸發(fā)策略執(zhí)行(如訂單支付后觸發(fā)對應調度策略);
    • 策略模式 + 簡單工廠:上下文自動選擇策略,簡化客戶端使用;
    • 觀察者模式 + 線程池:異步通知提升系統(tǒng)性能,避免阻塞。
  • 實戰(zhàn)注意事項:
    • 避免過度設計:簡單場景(如固定幾個觀察者/策略)可簡化實現(xiàn),無需嚴格遵循模式結構;
    • 線程安全優(yōu)先:多線程環(huán)境下,需保護共享資源(如觀察者列表、策略映射);
    • 內存管理:使用智能指針(shared_ptr/weak_ptr)避免內存泄漏;
    • 符合開閉原則:新增功能時,優(yōu)先通過擴展類實現(xiàn),而非修改現(xiàn)有代碼。

通過本章學習,你應能熟練運用觀察者模式和策略模式解決實際開發(fā)中的“交互通知”和“算法切換”問題,結合兩種模式的組合使用,編寫高內聚、低耦合、易擴展的 C++ 代碼。后續(xù)章節(jié)將繼續(xù)講解其他行為型設計模式(如裝飾者模式、適配器模式),進一步提升你的代碼設計能力。

到此這篇關于C++中觀察者模式與策略模式的實戰(zhàn)指南的文章就介紹到這了,更多相關C++觀察者模式與策略模式內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C/C++實現(xiàn)快速排序算法的兩種方式實例

    C/C++實現(xiàn)快速排序算法的兩種方式實例

    快速排序是一種采用分治思想,在實踐中通常運行較快一種排序算法,這篇文章主要給大家介紹了關于C/C++實現(xiàn)快速排序的兩種方式的相關資料,文中給出了詳細的示例代碼,需要的朋友可以參考下
    2021-08-08
  • C++容器適配與棧的實現(xiàn)及dequeque和優(yōu)先級詳解

    C++容器適配與棧的實現(xiàn)及dequeque和優(yōu)先級詳解

    這篇文章主要介紹了C++容器適配與棧的實現(xiàn)及dequeque和優(yōu)先級,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧
    2022-10-10
  • C語言超詳細梳理排序算法的使用

    C語言超詳細梳理排序算法的使用

    這篇文章主要介紹了C語言完成排序的實例,在C語言基本類型的排序中特別有用,下面我們一起進入文章學習更詳細的內容吧,需要的朋友可以參考下
    2022-03-03
  • c++函數(shù)中的指針參數(shù)與地址參數(shù)區(qū)別介紹

    c++函數(shù)中的指針參數(shù)與地址參數(shù)區(qū)別介紹

    c++函數(shù)中的指針參數(shù)與地址參數(shù)區(qū)別介紹;可供參考
    2012-11-11
  • C++ 的三種訪問權限與三種繼承方式

    C++ 的三種訪問權限與三種繼承方式

    我們知道C++中的類,有三種訪問權限(也稱作訪問控制),它們分別是public、protected、private,C++中繼承的方式還有多種。下面通過本文給大家詳細介紹,對c++中的訪問權限和繼承方式感興趣的朋友一起看看吧
    2016-11-11
  • C語言控制臺打磚塊小游戲

    C語言控制臺打磚塊小游戲

    這篇文章主要為大家詳細介紹了C語言控制臺打磚塊小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • C++ 數(shù)字的反轉實現(xiàn)實例

    C++ 數(shù)字的反轉實現(xiàn)實例

    這篇文章主要介紹了C++ 數(shù)字的反轉實現(xiàn)實例的相關資料,需要的朋友可以參考下
    2017-06-06
  • C++類中的六大默認成員函數(shù)詳解

    C++類中的六大默認成員函數(shù)詳解

    這篇文章主要介紹了C++類中的六大默認成員函數(shù),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • C++語言設計實現(xiàn)五子棋

    C++語言設計實現(xiàn)五子棋

    這篇文章主要為大家詳細介紹了C++語言設計實現(xiàn)五子棋,包括數(shù)據(jù)結構和對象設計及主函數(shù)調用實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • C語言實現(xiàn)車票管理系統(tǒng)

    C語言實現(xiàn)車票管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)車票管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05

最新評論

漳浦县| 海淀区| 河西区| 荥阳市| 沁水县| 古田县| 永宁县| 偃师市| 礼泉县| 平阴县| 鄂尔多斯市| 徐闻县| 承德市| 象山县| 吴川市| 淄博市| 兴业县| 安多县| 瓦房店市| 靖远县| 建湖县| 晋江市| 乐平市| 原平市| 基隆市| 化德县| 云龙县| 梁河县| 宿迁市| 香港| 水城县| 钟祥市| 新巴尔虎左旗| 保山市| 辽阳县| 福安市| 民丰县| 府谷县| 吉安县| 渭南市| 平定县|