C++ 设计模式原理与实战大全-架构师必学课程 | 完结

获课地址:666it.top/14228/

行为型模式核心------观察者、策略与责任链

字数:约1350字

引言

行为型设计模式主要负责对象间的高效沟通和职责委派。它们不是关于对象如何创建的,也不是关于对象和类如何组合的,而是关于对象之间如何交互以及如何分配责任的。本文将聚焦于三种极其重要的行为型模式:观察者模式策略模式责任链模式

一、观察者模式:构建松耦合的事件驱动系统

1.1 模式意图

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

1.2 C++实现(现代风格)

我们将使用std::vectorstd::function来实现一个灵活且类型安全的观察者模式。

cpp

arduino 复制代码
#include <iostream>
#include <vector>
#include <functional>
#include <algorithm>
#include <memory>

// 前置声明
class WeatherStation;

// 观察者基类 (传统方式,也可用function替代)
class Observer {
public:
    virtual ~Observer() = default;
    virtual void update(float temperature, float humidity, float pressure) = 0;
};

// 显示接口
class DisplayElement {
public:
    virtual ~DisplayElement() = default;
    virtual void display() const = 0;
};

// 主题接口
class Subject {
public:
    virtual ~Subject() = default;
    virtual void registerObserver(std::shared_ptr<Observer> o) = 0;
    virtual void removeObserver(std::shared_ptr<Observer> o) = 0;
    virtual void notifyObservers() = 0;
};

// 具体主题:气象站
class WeatherStation : public Subject {
private:
    std::vector<std::shared_ptr<Observer>> observers_;
    float temperature_;
    float humidity_;
    float pressure_;

public:
    void registerObserver(std::shared_ptr<Observer> o) override {
        observers_.push_back(o);
    }

    void removeObserver(std::shared_ptr<Observer> o) override {
        observers_.erase(
            std::remove(observers_.begin(), observers_.end(), o),
            observers_.end()
        );
    }

    void notifyObservers() override {
        for (auto& observer : observers_) {
            observer->update(temperature_, humidity_, pressure_);
        }
    }

    // 当气象测量更新时调用此方法
    void measurementsChanged() {
        notifyObservers();
    }

    // 设置新的测量数据
    void setMeasurements(float temperature, float humidity, float pressure) {
        temperature_ = temperature;
        humidity_ = humidity;
        pressure_ = pressure;
        measurementsChanged();
    }
};

// 具体观察者:当前状况显示
class CurrentConditionsDisplay : public Observer, public DisplayElement {
private:
    float temperature_;
    float humidity_;
    std::weak_ptr<Subject> weatherData_;

public:
    explicit CurrentConditionsDisplay(std::shared_ptr<Subject> weatherData)
        : weatherData_(weatherData) {
        weatherData->registerObserver(std::shared_ptr<Observer>(this, [](Observer*){})); // 小心使用this
        // 生产环境中建议使用enable_shared_from_this
    }

    void update(float temperature, float humidity, float pressure) override {
        temperature_ = temperature;
        humidity_ = humidity;
        display();
    }

    void display() const override {
        std::cout << "Current conditions: " << temperature_
                  << "F degrees and " << humidity_ << "% humidity" << std::endl;
    }
};

// 使用std::function的现代观察者实现 (更灵活)
template <typename... Args>
class Event {
public:
    using Callback = std::function<void(Args...)>;

    void subscribe(Callback callback) {
        callbacks_.push_back(callback);
    }

    void notify(Args... args) {
        for (auto& callback : callbacks_) {
            callback(args...);
        }
    }

private:
    std::vector<Callback> callbacks_;
};

// 一个使用现代观察者的简单按钮类
class Button {
public:
    Event<> onClick;

    void click() {
        std::cout << "Button clicked!" << std::endl;
        onClick.notify();
    }
};

class MessageService {
public:
    void sendMessage() {
        std::cout << "Message sent: Button was clicked!" << std::endl;
    }
};

// 实战应用
int main() {
    // 传统观察者模式应用
    auto weatherStation = std::make_shared<WeatherStation>();
    auto currentDisplay = std::make_shared<CurrentConditionsDisplay>(weatherStation);

    // 模拟新的气象数据到达
    weatherStation->setMeasurements(80, 65, 30.4f);
    weatherStation->setMeasurements(82, 70, 29.2f);

    std::cout << "\n--- Modern Observer with std::function ---\n";
    // 现代观察者模式应用
    Button button;
    MessageService msgService;

    // 订阅事件
    button.onClick.subscribe([&msgService]() { msgService.sendMessage(); });
    button.onClick.subscribe([]() { std::cout << "Logging click event..." << std::endl; });

    // 触发事件
    button.click();

    return 0;
}

1.3 模式应用场景

  • GUI工具包中的事件处理系统。
  • 发布-订阅系统。
  • MVC架构中,模型与视图的联动。

二、策略模式:自由切换算法家族

2.1 模式意图

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。策略模式使得算法可独立于使用它的客户而变化。

2.2 代码实现:支付策略

假设我们有一个电商系统,需要支持多种支付方式。

cpp

c 复制代码
#include <iostream>
#include <memory>
#include <string>

// 策略接口
class PaymentStrategy {
public:
    virtual ~PaymentStrategy() = default;
    virtual void pay(int amount) = 0;
};

// 具体策略A:信用卡支付
class CreditCardPayment : public PaymentStrategy {
private:
    std::string name_;
    std::string cardNumber_;
public:
    CreditCardPayment(const std::string& name, const std::string& cardNumber)
        : name_(name), cardNumber_(cardNumber) {}

    void pay(int amount) override {
        std::cout << "Paid $" << amount << " using Credit Card (" << cardNumber_ << ")" << std::endl;
    }
};

// 具体策略B:PayPal支付
class PayPalPayment : public PaymentStrategy {
private:
    std::string email_;
public:
    PayPalPayment(const std::string& email) : email_(email) {}

    void pay(int amount) override {
        std::cout << "Paid $" << amount << " using PayPal (" << email_ << ")" << std::endl;
    }
};

// 具体策略C:加密货币支付
class CryptoPayment : public PaymentStrategy {
private:
    std::string walletAddress_;
public:
    CryptoPayment(const std::string& walletAddress) : walletAddress_(walletAddress) {}

    void pay(int amount) override {
        std::cout << "Paid $" << amount << " using Cryptocurrency (" << walletAddress_ << ")" << std::endl;
    }
};

// 上下文:购物车
class ShoppingCart {
private:
    std::unique_ptr<PaymentStrategy> paymentStrategy_;
public:
    void setPaymentStrategy(std::unique_ptr<PaymentStrategy> strategy) {
        paymentStrategy_ = std::move(strategy);
    }

    void checkout(int amount) {
        if (paymentStrategy_) {
            paymentStrategy_->pay(amount);
        } else {
            std::cout << "No payment method selected!" << std::endl;
        }
    }
};

// 实战应用
int main() {
    ShoppingCart cart;

    // 用户选择信用卡支付
    cart.setPaymentStrategy(std::make_unique<CreditCardPayment>("John Doe", "1234-5678-9012-3456"));
    cart.checkout(100);

    // 用户切换为PayPal支付
    cart.setPaymentStrategy(std::make_unique<PayPalPayment>("john.doe@example.com"));
    cart.checkout(250);

    // 用户切换为加密货币支付
    cart.setPaymentStrategy(std::make_unique<CryptoPayment>("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"));
    cart.checkout(500);

    return 0;
}

2.3 模式优点

  • 消除了大量的条件判断语句(如if-else或switch-case)。
  • 提供了管理相关算法族的办法。
  • 支持开闭原则,易于扩展新的算法。

三、责任链模式:构建灵活的处理流水线

3.1 模式意图

使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

3.2 代码实现:日志处理器

构建一个不同级别的日志处理器链(DEBUG -> INFO -> ERROR)。

cpp

c 复制代码
#include <iostream>
#include <memory>
#include <string>

enum LogLevel {
    DEBUG,
    INFO,
    ERROR
};

// 处理器接口
class Logger {
protected:
    LogLevel level_;
    std::unique_ptr<Logger> nextLogger_; // 链中的下一个处理器
public:
    Logger(LogLevel level) : level_(level) {}

    // 设置下一个处理器
    void setNext(std::unique_ptr<Logger> nextLogger) {
        nextLogger_ = std::move(nextLogger);
    }

    // 处理请求
    void logMessage(LogLevel level, const std::string& message) {
        if (level_ <= level) { // 如果级别足够处理,则处理
            write(message);
        }
        // 传递给链上的下一个处理器
        if (nextLogger_ != nullptr) {
            nextLogger_->logMessage(level, message);
        }
    }

    virtual void write(const std::string& message) = 0;
};

// 具体处理器A:控制台日志
class ConsoleLogger : public Logger {
public:
    ConsoleLogger(LogLevel level) : Logger(level) {}

    void write(const std::string& message) override {
        std::cout << "Standard Console::Logger: " << message << std::endl;
    }
};

// 具体处理器B:文件日志
class FileLogger : public Logger {
public:
    FileLogger(LogLevel level) : Logger(level) {}

    void write(const std::string& message) override {
        std::cout << "File::Logger: " << message << std::endl;
    }
};

// 具体处理器C:错误日志(发送邮件)
class ErrorLogger : public Logger {
public:
    ErrorLogger(LogLevel level) : Logger(level) {}

    void write(const std::string& message) override {
        std::cout << "Error Console::Logger: " << message << std::endl;
        // 这里可以模拟发送邮件或通知管理员
        std::cout << "Sending email to admin regarding error..." << std::endl;
    }
};

// 实战应用:构建责任链
int main() {
    // 构建责任链: DEBUG -> INFO -> ERROR
    auto errorLogger = std::make_unique<ErrorLogger>(ERROR);
    auto fileLogger = std::make_unique<FileLogger>(INFO);
    auto consoleLogger = std::make_unique<ConsoleLogger>(DEBUG);

    // 设置链的顺序
    fileLogger->setNext(std::move(errorLogger));
    consoleLogger->setNext(std::move(fileLogger));

    // consoleLogger现在是链的头
    auto loggerChain = std::move(consoleLogger);

    // 测试日志消息
    loggerChain->logMessage(DEBUG, "This is a debug level information.");
    std::cout << "------------------------" << std::endl;
    loggerChain->logMessage(INFO, "This is an info level information.");
    std::cout << "------------------------" << std::endl;
    loggerChain->logMessage(ERROR, "This is an error level information.");

    return 0;
}

3.3 模式应用场景

  • 多个对象可以处理一个请求,但具体由哪个对象处理在运行时自动决定。
  • 需要在不明确指定接收者的情况下,向多个对象中的一个提交请求。
  • 可动态指定一组对象处理请求。

总结

观察者、策略和责任链模式是行为型模式中的三大支柱。观察者 解耦了事件发布者和订阅者,策略 让算法可以独立变化和切换,而责任链则构建了一条灵活的请求处理流水线。掌握它们,能够极大地提升你设计松耦合、高可扩展性C++系统的能力。在下一篇文章中,我们将进行终极实战,将这些模式综合运用于一个企业级项目案例中。

相关推荐
zhuzhuxia⌓‿⌓3 小时前
线性表的顺序和链式存储
数据结构·c++·算法
小苏兮3 小时前
【C++】stack与queue的使用与模拟实现
开发语言·c++
杨小码不BUG3 小时前
小鱼的数字游戏:C++实现与算法分析(洛谷P1427)
c++·算法·数组·信奥赛·csp-j/s
高山有多高3 小时前
栈:“后进先出” 的艺术,撑起程序世界的底层骨架
c语言·开发语言·数据结构·c++·算法
普罗米修斯4 小时前
C++ 设计模式理论与实战大全【共73课时】
c++·后端
普罗米修斯4 小时前
C++ 设计模式原理与实战大全-架构师必学课程 | 完结
c++·后端
夜月yeyue5 小时前
个人写HTOS移植shell
c++·mcu·算法·性能优化·架构·mfc
ajassi20005 小时前
开源 C++ QT QML 开发(九)文件--文本和二进制
c++·qt·开源
-森屿安年-5 小时前
C++ 类与对象
开发语言·c++