设计模式学习(3)-行为型模式
文章目录
- 命令模式(Command Pattern)
- UML类图
- 代码示例
- 中介者模式(Mediator Pattern)
- UML类图
- 代码示例
- 观察者模式(Observer Pattern)
- UML类图
- 代码示例
- 状态模式(State Pattern)
- UML类图
- 代码示例
- 策略模式(Strategy Pattern)
- UML类图
- 代码示例
命令模式(Command Pattern)
它将一个请求封装成一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。可以单独执行每一个命令,也可以将命令封装成一个命令宏从而批量执行命令。
UML类图

LightOnCommand、LightOffCommand、FanOnCommand、FanOffCommand与Command是继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。LightOnCommand和LightOffCommand与Light是依赖关系,使用的是虚线箭头,箭头指向被依赖对象。FanOnCommand和FanOffCommand与Fan是依赖关系,使用的是虚线箭头,箭头指向被依赖对象。MacroCommand与Command是继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。同时,MacroCommand与各Command子类是组合关系,使用的是实心菱形箭头实线,箭头指向被组合对象。RemoteControl与各Command子类是组合关系,使用的是实心菱形箭头实线,箭头指向被组合对象。
代码示例
#include <iostream>
#include <vector>
#include <stack>
#include <memory>// 命令接口
class Command {
public:virtual ~Command() = default;virtual void execute() = 0;virtual void undo() = 0; // 支持撤销操作
};// 接收者1:灯
class Light {std::string location_;bool isOn_ = false;
public:explicit Light(const std::string& location) : location_(location) {}void on() {isOn_ = true;std::cout << location_ << "的灯打开了" << std::endl;}void off() {isOn_ = false;std::cout << location_ << "的灯关闭了" << std::endl;}
};// 接收者2:风扇
class Fan {std::string location_;enum Speed { Off, Low, Medium, High };Speed speed_ = Off;
public:explicit Fan(const std::string& location) : location_(location) {}void on() {speed_ = Low;std::cout << location_ << "的风扇启动(低速)" << std::endl;}void off() {speed_ = Off;std::cout << location_ << "的风扇关闭" << std::endl;}void setSpeed(Speed speed) {speed_ = speed;static const char* speedNames[] = {"关闭", "低速", "中速", "高速"};std::cout << location_ << "的风扇速度设置为" << speedNames[speed_] << std::endl;}Speed getSpeed() const { return speed_; }
};// 具体命令:打开灯
class LightOnCommand : public Command {
private:Light* light_;
public:explicit LightOnCommand(Light* light) : light_(light) {}void execute() override {light_->on();}void undo() override {light_->off();}
};// 具体命令:关闭灯
class LightOffCommand : public Command {
private:Light* light_;
public:explicit LightOffCommand(Light* light) : light_(light) {}void execute() override {light_->off();}void undo() override {light_->on();}
};// 具体命令:开启风扇低速
class FanOnCommand : public Command {
private:Fan* fan_;Fan::Speed prevSpeed_;
public:explicit FanOnCommand(Fan* fan) : fan_(fan), prevSpeed_(Fan::Off) {}void execute() override {prevSpeed_ = fan_->getSpeed();fan_->on();}void undo() override {fan_->setSpeed(prevSpeed_);}
};// 具体命令:关闭风扇
class FanOffCommand : public Command {
private:Fan* fan_;Fan::Speed prevSpeed_;
public:explicit FanOffCommand(Fan* fan) : fan_(fan), prevSpeed_(Fan::Off) {}void execute() override {prevSpeed_ = fan_->getSpeed();fan_->off();}void undo() override {fan_->setSpeed(prevSpeed_);}
};// 宏命令,执行一组命令
class MacroCommand : public Command {
private:std::vector<std::shared_ptr<Command>> commands_;
public:void add(const std::shared_ptr<Command>& command) {commands_.push_back(command);}void execute() override {for (auto& cmd : commands_) {cmd->execute();}}void undo() override {// 逆序撤销for (auto it = commands_.rbegin(); it != commands_.rend(); ++it) {(*it)->undo();}}
};// 调用者 - 遥控器
class RemoteControl {
private:std::stack<std::shared_ptr<Command>> history_; // 支持撤销的命令历史栈
public:void submitCommand(const std::shared_ptr<Command>& cmd) {cmd->execute();history_.push(cmd);}void undo() {if (!history_.empty()) {auto cmd = history_.top();cmd->undo();history_.pop();} else {std::cout << "没有命令可以撤销" << std::endl;}}
};int main() {Light livingRoomLight("客厅");Fan ceilingFan("客厅");RemoteControl remote;// 创建灯的打开关闭命令auto lightOn = std::make_shared<LightOnCommand>(&livingRoomLight);auto lightOff = std::make_shared<LightOffCommand>(&livingRoomLight);// 创建风扇的开、关命令auto fanOn = std::make_shared<FanOnCommand>(&ceilingFan);auto fanOff = std::make_shared<FanOffCommand>(&ceilingFan);// 单独打开灯remote.submitCommand(lightOn);// 单独关闭灯remote.submitCommand(lightOff);// 打开风扇remote.submitCommand(fanOn);// 撤销风扇开启remote.undo();// 创建宏命令,打开灯和风扇auto partyOn = std::make_shared<MacroCommand>();partyOn->add(lightOn);partyOn->add(fanOn);// 创建宏命令,关闭灯和风扇auto partyOff = std::make_shared<MacroCommand>();partyOff->add(lightOff);partyOff->add(fanOff);// 执行宏命令std::cout << "\n开启派对模式:" << std::endl;remote.submitCommand(partyOn);// 撤销宏命令std::cout << "\n撤销派对模式:" << std::endl;remote.undo();// 关闭派对模式std::cout << "\n关闭派对模式:" << std::endl;remote.submitCommand(partyOff);return 0;
}
- 这里的RemoteControl和MacroCommand并不是必须的引入的目的主要是做管理和回滚命令。
- MacroCommand属于将多个Command组合成一系列动作,因此,它既继承了Command又依赖Command子类运行。
中介者模式(Mediator Pattern)
它通过引入一个中介者对象来封装一组对象之间的交互,使各个对象不需要显式地相互引用,从而降低对象之间的耦合度,提高系统的灵活性和可维护性。例如:有一个聊天室系统,多个用户发送消息,不直接发送给彼此,而是通过聊天室(中介者)转发消息。
UML类图

ChatMediator与ChatRoom是继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。User与ConcreteUser是继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。ConcreteUser与ChatRoom是依赖关系,使用的是虚线箭头,箭头指向被依赖对象。
代码示例
#include <iostream>
#include <string>
#include <vector>
#include <memory>// 抽象中介者
class ChatMediator {
public:virtual void sendMessage(const std::string& msg, int userId) = 0;virtual void addUser(int userId) = 0;virtual ~ChatMediator() = default;
};// 具体中介者
class ChatRoom : public ChatMediator {
private:std::vector<int> users; // 简化用户存储,只存用户ID
public:void sendMessage(const std::string& msg, int userId) override {for (int id : users) {if (id != userId) {std::cout << "User" << id << " received: " << msg << std::endl;}}}void addUser(int userId) override {users.push_back(userId);}
};// 抽象同事类
class User {
protected:ChatMediator& mediator;int id;
public:User(ChatMediator& m, int uid) : mediator(m), id(uid) {mediator.addUser(id);}virtual void send(const std::string& msg) = 0;virtual void receive(const std::string& msg) {std::cout << "User" << id << " received: " << msg << std::endl;}virtual ~User() = default;
};// 具体同事类
class ConcreteUser : public User {
public:ConcreteUser(ChatMediator& m, int uid) : User(m, uid) {}void send(const std::string& msg) override {std::cout << "User" << id << " sends: " << msg << std::endl;mediator.sendMessage(msg, id);}
};int main() {ChatRoom chatroom;ConcreteUser user1(chatroom, 1);ConcreteUser user2(chatroom, 2);ConcreteUser user3(chatroom, 3);user1.send("Hello, everyone!");user2.send("Hi User1!");user3.send("Good morning!");return 0;
}
观察者模式(Observer Pattern)
是一种常用的软件设计模式,它定义了一种一对多的依赖关系,使得当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
UML类图

CurrentConditionsDisplay、StatisticsDisplay与Observer是继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。WeatherData与Subject是继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。Subject子类与各Observer子类是依赖关系,使用的是虚线箭头,箭头指向被依赖对象。
代码示例
#include <iostream>
#include <vector>
#include <algorithm>// 抽象观察者
class Observer {
public:virtual ~Observer() = default;virtual void update(float temperature, float humidity) = 0;
};// 抽象主题
class Subject {
public:virtual ~Subject() = default;virtual void registerObserver(Observer* observer) = 0;virtual void removeObserver(Observer* observer) = 0;virtual void notifyObservers() = 0;
};// 具体主题——天气数据
class WeatherData : public Subject {
private:std::vector<Observer*> observers;float temperature;float humidity;public:void registerObserver(Observer* observer) override {observers.push_back(observer);}void removeObserver(Observer* observer) override {observers.erase(std::remove(observers.begin(), observers.end(), observer), observers.end());}void notifyObservers() override {for (Observer* observer : observers) {observer->update(temperature, humidity);}}// 当天气数据更新时调用此方法void setMeasurements(float temp, float hum) {temperature = temp;humidity = hum;notifyObservers();}
};// 具体观察者——显示设备1
class CurrentConditionsDisplay : public Observer {
private:float temperature;float humidity;public:void update(float temp, float hum) override {temperature = temp;humidity = hum;display();}void display() {std::cout << "Current conditions: " << temperature << "°C and " << humidity << "% humidity\n";}
};// 具体观察者——显示设备2
class StatisticsDisplay : public Observer {
private:float maxTemp = -1000;float minTemp = 1000;float tempSum = 0;int numReadings = 0;public:void update(float temp, float hum) override {tempSum += temp;numReadings++;if (temp > maxTemp) maxTemp = temp;if (temp < minTemp) minTemp = temp;display();}void display() {std::cout << "Avg/Max/Min temperature = " << (tempSum / numReadings)<< "/" << maxTemp << "/" << minTemp << "\n";}
};int main() {WeatherData weatherData;CurrentConditionsDisplay currentDisplay;StatisticsDisplay statsDisplay;// 注册观察者weatherData.registerObserver(¤tDisplay);weatherData.registerObserver(&statsDisplay);// 模拟数据变化weatherData.setMeasurements(25.0f, 65.0f);weatherData.setMeasurements(27.0f, 70.0f);weatherData.setMeasurements(23.0f, 90.0f);// 移除观察者后数据变化weatherData.removeObserver(¤tDisplay);weatherData.setMeasurements(26.0f, 80.0f);return 0;
}
状态模式(State Pattern)
将对象的状态封装到独立的状态类中,并通过状态类切换来改变对象的行为。这样即使状态变化导致行为变化,也不会引起客户端代码的改变,这个设计模式最典型的是TCP连接过程。
UML类图

ClosedState、ListenState、EstablishedState与TcpState是继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。TcpConnection与各TcpState子类是依赖关系,使用的是虚线箭头,箭头指向被依赖对象。
代码示例
#include <iostream>
#include <memory>// 前向声明
class TcpState;// 环境类
class TcpConnection {
public:TcpConnection(std::shared_ptr<TcpState> state) : state_(state) {}void setState(std::shared_ptr<TcpState> state) {state_ = state;}void open() {state_->open(*this);}void close() {state_->close(*this);}void acknowledge() {state_->acknowledge(*this);}private:std::shared_ptr<TcpState> state_;
};// 抽象状态接口
class TcpState {
public:virtual ~TcpState() = default;virtual void open(TcpConnection& connection) = 0;virtual void close(TcpConnection& connection) = 0;virtual void acknowledge(TcpConnection& connection) = 0;
};// 具体状态:Closed
class ClosedState : public TcpState {
public:void open(TcpConnection& connection) override {std::cout << "打开连接,进入监听状态\n";connection.setState(std::make_shared<ListenState>());}void close(TcpConnection& /*connection*/) override {std::cout << "连接已经关闭\n";}void acknowledge(TcpConnection& /*connection*/) override {std::cout << "连接关闭,无法接收确认\n";}
};// 具体状态:Listen
class ListenState : public TcpState {
public:void open(TcpConnection& connection) override {std::cout << "连接建立,进入已建立状态\n";connection.setState(std::make_shared<EstablishedState>());}void close(TcpConnection& connection) override {std::cout << "关闭连接,进入关闭状态\n";connection.setState(std::make_shared<ClosedState>());}void acknowledge(TcpConnection& /*connection*/) override {std::cout << "监听状态,等待连接建立\n";}
};// 具体状态:Established
class EstablishedState : public TcpState {
public:void open(TcpConnection& /*connection*/) override {std::cout << "连接已建立,不能重新打开\n";}void close(TcpConnection& connection) override {std::cout << "关闭连接,进入关闭状态\n";connection.setState(std::make_shared<ClosedState>());}void acknowledge(TcpConnection& /*connection*/) override {std::cout << "接收确认数据\n";}
};// 测试主函数
int main() {auto closed = std::make_shared<ClosedState>();TcpConnection connection(closed);connection.open(); // Closed -> Listenconnection.acknowledge(); // Listen状态,等待连接建立connection.open(); // Listen -> Establishedconnection.acknowledge(); // Established 接收确认数据connection.close(); // Established -> Closedconnection.close(); // 已关闭状态,无法关闭return 0;
}
策略模式(Strategy Pattern)
它定义了一系列算法,把它们一个个封装起来,并使它们可以互相替换。策略模式让算法独立于使用它的客户而变化。策略模式的核心意图:
- 将算法族封装起来,使它们可以互换。
- 策略模式让算法独立于使用它的客户端独立变化。
- 客户端在运行时可以自由选择具体策略实现。
UML类图

NoDiscount、FullReduction、PercentageDiscount与DiscountStrategy是继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。ShoppingCarts与各DiscountStrategy子类是依赖关系,使用的是虚线箭头,箭头指向被依赖对象。
代码示例
#include <iostream>
#include <memory>// 抽象策略类
class DiscountStrategy {
public:virtual ~DiscountStrategy() = default;virtual double calculate(double price) const = 0;
};// 具体策略类 - 无折扣
class NoDiscount : public DiscountStrategy {
public:double calculate(double price) const override {return price;}
};// 具体策略类 - 满减(如满100减20)
class FullReduction : public DiscountStrategy {
public:double calculate(double price) const override {if (price >= 100.0)return price - 20.0;return price;}
};// 具体策略类 - 打折(如打8折)
class PercentageDiscount : public DiscountStrategy {
public:PercentageDiscount(double discount) : discount_(discount) {}double calculate(double price) const override {return price * discount_;}private:double discount_; // 0.8 表示打8折
};// 上下文类
class ShoppingCart {
public:void setDiscountStrategy(std::shared_ptr<DiscountStrategy> strategy) {strategy_ = strategy;}double calculatePrice(double price) const {if (strategy_) {return strategy_->calculate(price);}return price; // 默认无折扣}private:std::shared_ptr<DiscountStrategy> strategy_;
};int main() {ShoppingCart cart;double originalPrice = 120.0;std::cout << "原价: " << originalPrice << "\n";// 使用无折扣策略cart.setDiscountStrategy(std::make_shared<NoDiscount>());std::cout << "无折扣价: " << cart.calculatePrice(originalPrice) << "\n";// 使用满减策略cart.setDiscountStrategy(std::make_shared<FullReduction>());std::cout << "满减价: " << cart.calculatePrice(originalPrice) << "\n";// 使用打折策略(8折)cart.setDiscountStrategy(std::make_shared<PercentageDiscount>(0.8));std::cout << "打折价: " << cart.calculatePrice(originalPrice) << "\n";return 0;
}
