获课地址:666it.top/14228/
行为型模式核心------观察者、策略与责任链
字数:约1350字
引言
行为型设计模式主要负责对象间的高效沟通和职责委派。它们不是关于对象如何创建的,也不是关于对象和类如何组合的,而是关于对象之间如何交互以及如何分配责任的。本文将聚焦于三种极其重要的行为型模式:观察者模式 、策略模式 和责任链模式。
一、观察者模式:构建松耦合的事件驱动系统
1.1 模式意图
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
1.2 C++实现(现代风格)
我们将使用std::vector
和std::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++系统的能力。在下一篇文章中,我们将进行终极实战,将这些模式综合运用于一个企业级项目案例中。