状态模式允许对象在其内部状态改变时改变其行为,使得对象看起来如同修改了其类。该模式将状态相关的行为封装在独立的状态类中,并通过统一接口进行切换。
通过切换状态来实现切换行为。
当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了
核心组件:
场景:电梯有多种状态(开门、关门、运行、停止),不同状态下响应不同命令。
#include
#include
// 前置声明
class Elevator;
// 抽象状态类
class ElevatorState {
public:
virtual ~ElevatorState() = default;
virtual void openDoor(Elevator* elevator) = 0;
virtual void closeDoor(Elevator* elevator) = 0;
virtual void run(Elevator* elevator) = 0;
virtual void stop(Elevator* elevator) = 0;
virtual std::string getStateName() const = 0;
};
// 上下文类:电梯
class Elevator {
private:
ElevatorState* currentState;
public:
explicit Elevator(ElevatorState* state) : currentState(state) {}
~Elevator() { delete currentState; }
void setState(ElevatorState* state) {
std::cout << "电梯状态从 " << currentState->getStateName()
<< " 变为 " << state->getStateName() << std::endl;
delete currentState;
currentState = state;
}
// 委托给当前状态处理
void openDoor() { currentState->openDoor(this); }
void closeDoor() { currentState->closeDoor(this); }
void run() { currentState->run(this); }
void stop() { currentState->stop(this); }
};
// 具体状态:开门状态
class DoorOpenState : public ElevatorState {
public:
void openDoor(Elevator* elevator) override {
std::cout << "电梯门已开,无需重复操作" << std::endl;
}
void closeDoor(Elevator* elevator) override {
std::cout << "电梯门正在关闭..." << std::endl;
elevator->setState(new DoorClosedState());
}
void run(Elevator* elevator) override {
std::cout << "电梯门未关,无法运行" << std::endl;
}
void stop(Elevator* elevator) override {
std::cout << "电梯未运行,无需停止" << std::endl;
}
std::string getStateName() const override { return "开门状态"; }
};
// 具体状态:关门状态
class DoorClosedState : public ElevatorState {
public:
void openDoor(Elevator* elevator) override {
std::cout << "电梯门正在打开..." << std::endl;
elevator->setState(new DoorOpenState());
}
void closeDoor(Elevator* elevator) override {
std::cout << "电梯门已关闭,无需重复操作" << std::endl;
}
void run(Elevator* elevator) override {
std::cout << "电梯开始运行..." << std::endl;
elevator->setState(new RunningState());
}
void stop(Elevator* elevator) override {
std::cout << "电梯未运行,无需停止" << std::endl;
}
std::string getStateName() const override { return "关门状态"; }
};
// 具体状态:运行状态
class RunningState : public ElevatorState {
public:
void openDoor(Elevator* elevator) override {
std::cout << "电梯运行中,不能开门" << std::endl;
}
void closeDoor(Elevator* elevator) override {
std::cout << "电梯运行中,门已关闭" << std::endl;
}
void run(Elevator* elevator) override {
std::cout << "电梯已在运行中" << std::endl;
}
void stop(Elevator* elevator) override {
std::cout << "电梯正在停止..." << std::endl;
elevator->setState(new StoppedState());
}
std::string getStateName() const override { return "运行状态"; }
};
// 具体状态:停止状态
class StoppedState : public ElevatorState {
public:
void openDoor(Elevator* elevator) override {
std::cout << "电梯门正在打开..." << std::endl;
elevator->setState(new DoorOpenState());
}
void closeDoor(Elevator* elevator) override {
std::cout << "电梯门已关闭,无需重复操作" << std::endl;
}
void run(Elevator* elevator) override {
std::cout << "电梯开始运行..." << std::endl;
elevator->setState(new RunningState());
}
void stop(Elevator* elevator) override {
std::cout << "电梯已停止,无需重复操作" << std::endl;
}
std::string getStateName() const override { return "停止状态"; }
};
// 客户端代码
int main() {
// 创建电梯,初始状态为开门
Elevator elevator(new DoorOpenState());
// 执行一系列操作
elevator.closeDoor(); // 开门 -> 关门
elevator.run(); // 关门 -> 运行
elevator.openDoor(); // 运行中,无法开门
elevator.stop(); // 运行 -> 停止
elevator.openDoor(); // 停止 -> 开门
return 0;
}
解耦状态与行为:
if-else
或switch-case
。符合开闭原则:
状态转换显式化:
行为局部化:
维度 | 状态模式(State) | 策略模式(Strategy) |
---|---|---|
核心意图 | 封装基于状态的行为,状态间可自动转换 | 封装可互换的算法,由客户端主动选择 |
状态管理 | 状态由上下文或状态类自身管理,自动转换 | 策略由客户端管理,需显式切换 |
依赖关系 | 上下文依赖抽象状态,具体状态相互知晓 | 上下文依赖抽象策略,具体策略相互独立 |
使用场景 | 行为随状态变化而变化,状态转换逻辑复杂 | 算法可互相替换,客户端需灵活选择 |
对象行为依赖状态:
状态转换频繁:
条件语句复杂:
if-else
或switch-case
使代码难以维护时。共享状态实例:
状态工厂:
状态机框架:
内存管理:
状态爆炸:
状态转换逻辑:
状态模式是处理复杂状态逻辑的有效工具,通过将状态相关行为封装到独立类中,使代码更清晰、可维护和可扩展。
策略模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端。
核心组件:
场景:电商系统支持多种支付方式(信用卡、支付宝、微信支付)。
#include
#include
// 策略接口:支付方式
class PaymentStrategy {
public:
virtual ~PaymentStrategy() = default;
virtual void pay(double amount) const = 0;
};
// 具体策略:信用卡支付
class CreditCardPayment : public PaymentStrategy {
private:
std::string cardNumber;
std::string cvv;
std::string expiryDate;
public:
CreditCardPayment(const std::string& cardNum, const std::string& cvv, const std::string& expiry)
: cardNumber(cardNum), cvv(cvv), expiryDate(expiry) {}
void pay(double amount) const override {
std::cout << "使用信用卡支付: " << amount << " 元" << std::endl;
std::cout << "卡号: " << cardNumber << ", CVV: " << cvv << ", 有效期: " << expiryDate << std::endl;
}
};
// 具体策略:支付宝支付
class AlipayPayment : public PaymentStrategy {
private:
std::string userId;
public:
explicit AlipayPayment(const std::string& id) : userId(id) {}
void pay(double amount) const override {
std::cout << "使用支付宝支付: " << amount << " 元" << std::endl;
std::cout << "支付宝账户: " << userId << std::endl;
}
};
// 具体策略:微信支付
class WechatPayment : public PaymentStrategy {
private:
std::string openId;
public:
explicit WechatPayment(const std::string& id) : openId(id) {}
void pay(double amount) const override {
std::cout << "使用微信支付: " << amount << " 元" << std::endl;
std::cout << "微信ID: " << openId << std::endl;
}
};
// 上下文:订单
class Order {
private:
double amount;
PaymentStrategy* paymentStrategy;
public:
explicit Order(double orderAmount) : amount(orderAmount), paymentStrategy(nullptr) {}
~Order() { delete paymentStrategy; }
void setPaymentStrategy(PaymentStrategy* strategy) {
delete paymentStrategy;
paymentStrategy = strategy;
}
void processPayment() const {
if (!paymentStrategy) {
std::cout << "请先选择支付方式" << std::endl;
return;
}
paymentStrategy->pay(amount);
}
};
// 客户端代码
int main() {
// 创建订单
Order order(99.99);
// 选择支付方式(策略)
order.setPaymentStrategy(new CreditCardPayment("1234-5678-9012-3456", "123", "12/25"));
order.processPayment();
// 切换支付方式
order.setPaymentStrategy(new AlipayPayment("[email protected]"));
order.processPayment();
return 0;
}
算法可互换:
解耦算法与客户端:
扩展性强:
消除条件语句:
if-else
或switch-case
来选择算法。维度 | 策略模式(Strategy) | 状态模式(State) |
---|---|---|
核心意图 | 封装可互换的算法,由客户端主动选择 | 封装基于状态的行为,状态间可自动转换 |
状态管理 | 策略由客户端管理,需显式切换 | 状态由上下文或状态类自身管理,自动转换 |
依赖关系 | 上下文依赖抽象策略,具体策略相互独立 | 上下文依赖抽象状态,具体状态相互知晓 |
使用场景 | 算法可互相替换,客户端需灵活选择 | 行为随状态变化而变化,状态转换逻辑复杂 |
多种算法选择:
动态切换行为:
避免条件语句:
策略工厂:
参数化策略:
策略注册表:
客户端需了解策略:
策略数量控制:
策略共享:
策略模式是处理算法变化的有效工具,通过将算法封装在独立的策略类中,使代码更具灵活性和可维护性。
适配器模式是一种结构型设计模式,它允许将一个类的接口转换成客户期望的另一个接口。适配器让原本接口不兼容的类可以合作无间,其核心思想是通过一个中间组件(适配器)来兼容不同的接口。
需要的东西就在面前,但却不能使用,而短时间又无法改造它,于是我们就想办法适配它。比如笔记本电脑是不能什么电压都能用的,但国家不同,电压可能不相同也是事实,于是就用一个电源适配器,只要是电,不管多少伏,都能把电源变成需要的电压,这就是电源适配器的作用。适配器的意思就是使得一个东西适合另一个东西的东西。
适配器也可以看作“ 翻译 ”,使不兼容的两个系统间能够彼此沟通。
什么时候需要适配器?
在软件开发中,也就是系统的数据和行为都正确,但接口不符时,我们应该考虑用适配器,目的是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况,比如在需要对早期代码复用一些功能等应用上很有实际价值。
核心角色:
适配器模式有两种主要实现方式:
场景:将第三方矩形绘制库适配为统一的形状接口。
#include
#include
// 目标接口:形状
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
// 适配者:第三方矩形类(接口不兼容)
class ThirdPartyRectangle {
public:
void drawRectangle(double x1, double y1, double x2, double y2) {
std::cout << "第三方库绘制矩形:从 (" << x1 << "," << y1
<< ") 到 (" << x2 << "," << y2 << ")" << std::endl;
}
};
// 对象适配器:将矩形适配为形状接口
class RectangleAdapter : public Shape {
private:
ThirdPartyRectangle* adaptee; // 组合适配者
double x1, y1, x2, y2; // 矩形坐标
public:
RectangleAdapter(double x1, double y1, double x2, double y2)
: adaptee(new ThirdPartyRectangle()), x1(x1), y1(y1), x2(x2), y2(y2) {}
~RectangleAdapter() override { delete adaptee; }
// 实现目标接口方法
void draw() override {
adaptee->drawRectangle(x1, y1, x2, y2); // 转换调用
}
};
// 客户端代码
int main() {
// 使用适配器创建矩形(通过形状接口)
Shape* rectangle = new RectangleAdapter(10, 10, 50, 50);
rectangle->draw(); // 输出:第三方库绘制矩形:从 (10,10) 到 (50,50)
delete rectangle;
return 0;
}
// 目标接口(同上)
class Shape {
public:
virtual void draw() = 0;
virtual ~Shape() = default;
};
// 适配者(同上)
class ThirdPartyRectangle {
public:
void drawRectangle(double x1, double y1, double x2, double y2) {
std::cout << "第三方库绘制矩形:从 (" << x1 << "," << y1
<< ") 到 (" << x2 << "," << y2 << ")" << std::endl;
}
};
// 类适配器:通过多重继承同时实现目标接口和适配者
class RectangleAdapter : public Shape, private ThirdPartyRectangle {
private:
double x1, y1, x2, y2;
public:
RectangleAdapter(double x1, double y1, double x2, double y2)
: x1(x1), y1(y1), x2(x2), y2(y2) {}
// 实现目标接口方法
void draw() override {
drawRectangle(x1, y1, x2, y2); // 直接调用适配者方法
}
};
允许两个不兼容的接口互相适配:
class Shape {
public:
virtual void draw() = 0;
};
class Rectangle {
public:
virtual void drawRect(double x1, double y1, double x2, double y2) = 0;
};
class DoubleAdapter : public Shape, public Rectangle {
private:
Shape* shape;
Rectangle* rect;
public:
DoubleAdapter(Shape* s) : shape(s), rect(nullptr) {}
DoubleAdapter(Rectangle* r) : shape(nullptr), rect(r) {}
// 实现Shape接口
void draw() override {
if (rect) rect->drawRect(0, 0, 100, 100);
}
// 实现Rectangle接口
void drawRect(double x1, double y1, double x2, double y2) override {
if (shape) shape->draw();
}
};
接口兼容性:
松耦合设计:
开闭原则:
双向适配:
整合第三方库:
系统升级:
复用遗留代码:
统一多个相似接口:
与桥接模式的区别:
与装饰器模式的区别:
与外观模式的区别:
避免过度使用:
性能开销:
双向适配器复杂性:
适配器模式是解决接口不兼容问题的有效工具,通过引入中间层(适配器),使原本无法协作的类能够无缝集成。在实际开发中,它常用于整合第三方库、系统升级过渡或复用遗留代码。