当前位置: 首页 > news >正文

设计模式学习(3)-行为型模式

文章目录

  • 命令模式(Command Pattern)
    • UML类图
    • 代码示例
  • 中介者模式(Mediator Pattern)
    • UML类图
    • 代码示例
  • 观察者模式(Observer Pattern)
    • UML类图
    • 代码示例
  • 状态模式(State Pattern)
    • UML类图
    • 代码示例
  • 策略模式(Strategy Pattern)
    • UML类图
    • 代码示例

命令模式(Command Pattern)

它将一个请求封装成一个对象,从而使你可以用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及支持可撤销的操作。可以单独执行每一个命令,也可以将命令封装成一个命令宏从而批量执行命令。

UML类图

命令模式

  • LightOnCommandLightOffCommandFanOnCommandFanOffCommandCommand继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。
  • LightOnCommandLightOffCommandLight依赖关系,使用的是虚线箭头,箭头指向被依赖对象。
  • FanOnCommandFanOffCommandFan依赖关系,使用的是虚线箭头,箭头指向被依赖对象。
  • MacroCommandCommand继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。同时,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;
}
  • 这里的RemoteControlMacroCommand并不是必须的引入的目的主要是做管理和回滚命令。
  • MacroCommand属于将多个Command组合成一系列动作,因此,它既继承了Command又依赖Command子类运行。

中介者模式(Mediator Pattern)

它通过引入一个中介者对象来封装一组对象之间的交互,使各个对象不需要显式地相互引用,从而降低对象之间的耦合度,提高系统的灵活性和可维护性。例如:有一个聊天室系统,多个用户发送消息,不直接发送给彼此,而是通过聊天室(中介者)转发消息。

UML类图

中介者模式

  • ChatMediatorChatRoom继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。
  • UserConcreteUser继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。
  • ConcreteUserChatRoom依赖关系,使用的是虚线箭头,箭头指向被依赖对象。

代码示例

#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类图

观察者模式

  • CurrentConditionsDisplayStatisticsDisplayObserver继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。
  • WeatherDataSubject继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。
  • 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(&currentDisplay);weatherData.registerObserver(&statsDisplay);// 模拟数据变化weatherData.setMeasurements(25.0f, 65.0f);weatherData.setMeasurements(27.0f, 70.0f);weatherData.setMeasurements(23.0f, 90.0f);// 移除观察者后数据变化weatherData.removeObserver(&currentDisplay);weatherData.setMeasurements(26.0f, 80.0f);return 0;
}

状态模式(State Pattern)

将对象的状态封装到独立的状态类中,并通过状态类切换来改变对象的行为。这样即使状态变化导致行为变化,也不会引起客户端代码的改变,这个设计模式最典型的是TCP连接过程。

UML类图

状态模式

  • ClosedStateListenStateEstablishedStateTcpState继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。
  • 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类图

策略模式

  • NoDiscountFullReductionPercentageDiscountDiscountStrategy继承关系,使用的是空心三角箭头(空心箭头),箭头从子类指向父类。
  • 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;
}
http://www.dtcms.com/a/606851.html

相关文章:

  • Angular 2 架构:深度解析与最佳实践
  • 09-微服务原理篇(XXLJOB-幂等-MySQL)
  • 代码随想录训练营打卡Day45| 动态规划part12
  • 网站开发要考什么证wordpress xy 变装
  • 已知两个端点的位置、切矢量和曲率,构造一条五阶Bézier 曲线实现 G² 连续的方法
  • 显示 Markdown 的文件
  • 算法学习入门---模拟(C++)
  • 列表网做优化网站怎么样成都网站注册
  • 文库网站开发教程wordpress 绑定熊掌号
  • C语言在线编译器网站 | 提供快速、便捷的在线编程与调试平台
  • 免费高清视频素材网站品牌网站建设定制
  • 个人做的卖货网站团购网站开发
  • C++---const关键字 编译期约束保证数据的 只读性
  • 算法基础入门第一章
  • 家用除湿机方案开发,除湿机MCU控制方案设计
  • 搜狗推广做网站要钱吗wordpress首页调用指定文章
  • wordpress使用人数宁波seo在线优化公司
  • YOLO系列发展史与应用现状:从开山之作到实时目标检测的基石
  • 【电商微服务日志处理全方案】从MySQL瓶颈到大数据架构的实战转型
  • 蔬菜配送网站建设网络系统脆弱性的不安全因素
  • 常州想做个企业的网站找谁做注册公司需要交多少税
  • 反编译易语言程序 | 如何安全有效地进行易语言程序的反编译操作
  • 刺猬猫网站维护wordpress $post->id
  • 商城网站开发项目描述嘉兴建站公司
  • 从爆款到厂牌:解读游戏工业化的业务持续增长道路
  • 深度学习:学习率衰减(Learning Rate Decay)
  • 深度学习:RMSprop 优化算法详解
  • 盐城网站建设费用怎么判断一个网站是否使用帝国做的
  • 企业电子商务网站设计的原则做旅游宣传哪个网站好
  • 进程程序替换函数(Linux)