状态模式-C++实现

状态模式是一种行为型设计模式,它允许对象内部状态发生改变时改变其行为,它将行为封装在不同的状态对象中,在运行时通过切换不同的状态可以表现出不同的行为。

状态模式一般有三种角色:

1、状态接口:定义了状态对象所具有的公共接口,用于封装其相关行为。

2、具体状态:实现状态接口,在不同状态下表现不同的行为

3、环境类:维护一个当前状态对象的引用,并在其内部进行状态切换和行为的调用。环境类客户端根据当前状态对象的不同,调用不同的行为逻辑。

其实状态模式和策略模式非常相似,可以访问这篇文章,可以发现真的真的非常类似。

策略模式-C++实现

举例:

现在有一个订单系统,每一个订单有三种状态:待处理、已发送、已送达。不同的状态下它们的行为也会不同,
具体的行为包括:
1、待处理状态下订单可以取消、订单即将处理、订单还未送达,因为还没有处理订单;
2、已发送状态下订单不可以取消、订单已经处理、订单即将送达;
3、送达状态下订单不可以取消、订单已经处理、订单已经送达。

#include <iostream>
#include <memory>

// 抽象状态接口
class IOrderState
{
public:
	virtual ~IOrderState() {}

	// 取消行为
	virtual void Cancel() = 0;
	// 待处理行为
	virtual void Ship() = 0;
	// 已送达行为
	virtual void Deliver() = 0;
};

// 具体状态-待处理状态
class PendingState
	: public IOrderState
{
public:
	
	virtual void Cancel() override
	{
		std::cout << "订单待处理状态:取消订单" << std::endl;
	}

	virtual void Ship() override
	{
		std::cout << "订单待处理状态:订单即将处理" << std::endl;
	}

	virtual void Deliver() override
	{
		std::cout << "订单待处理状态:订单还未处理,没有送达" << std::endl;
	}
};

// 具体状态-已发送状态
class SendState
	: public IOrderState
{
public:

	virtual void Cancel() override
	{
		std::cout << "订单已发送状态:订单无法取消" << std::endl;
	}

	virtual void Ship() override
	{
		std::cout << "订单已发送状态:订单已经处理" << std::endl;
	}

	virtual void Deliver() override
	{
		std::cout << "订单已发送状态:订单即将送达" << std::endl;
	}
};

// 具体状态-已送达状态
class DeliveredState
	: public IOrderState
{
public:

	virtual void Cancel() override
	{
		std::cout << "订单已送达状态:订单无法取消" << std::endl;
	}

	virtual void Ship() override
	{
		std::cout << "订单已送达状态:订单已经处理" << std::endl;
	}

	virtual void Deliver() override
	{
		std::cout << "订单已送达状态:订单已经送达" << std::endl;
	}
};

// 环境类
class ContextState
{
public:

	ContextState()
	{
		// 订单初始状态是待处理
		orderState_ = std::make_shared<PendingState>();
	}

	// 切换当前状态
	void SetOrderState(std::shared_ptr<IOrderState> _orderState)
	{
		orderState_ = _orderState;
	}

	// 取消
	void Cancel()
	{
		orderState_->Cancel();
	}

	// 即将处理
	void Ship()
	{
		orderState_->Ship();
	}

	// 已送达
	void Deliver()
	{
		orderState_->Deliver();
	}

private:

	std::shared_ptr<IOrderState> orderState_;
};

测试:

void TestState()
{
	// 环境类对象
	std::shared_ptr<ContextState> context = std::make_shared<ContextState>();

	// 待处理状态
	std::shared_ptr<IOrderState> pendingState = std::make_shared<PendingState>();
	// 已发送状态
	std::shared_ptr<IOrderState> sendState = std::make_shared<SendState>();
	// 已送达状态
	std::shared_ptr<IOrderState> deliverState = std::make_shared<DeliveredState>();

	// 订单默认是待处理状态
	context->Cancel();
	context->Ship();
	context->Deliver();

	std::cout << "---------------------" << std::endl;

	// 切换成已发送状态
	context->SetOrderState(sendState);

	context->Cancel();
	context->Ship();
	context->Deliver();

	std::cout << "---------------------" << std::endl;

	// 切换成已送达状态
	context->SetOrderState(deliverState);

	context->Cancel();
	context->Ship();
	context->Deliver();

	std::cout << "---------------------" << std::endl;
}

输出:

订单待处理状态:取消订单
订单待处理状态:订单即将处理
订单待处理状态:订单还未处理,没有送达
---------------------
订单已发送状态:订单无法取消
订单已发送状态:订单已经处理
订单已发送状态:订单即将送达
---------------------
订单已送达状态:订单无法取消
订单已送达状态:订单已经处理
订单已送达状态:订单已经送达
---------------------

代码示例中,我们创建了一个抽象状态接口,定义订单取消、订单待处理、订单已送达三种行为。还创建了三个具体状态(订单待处理、订单已发送、订单已送达)实现了这三种行为方法,在环境类中我们实现了切换状态的方法和这三种行为方法。

根据输出我们可以发现在不同的状态下它们的行为也是不同的,比如在订单待处理状态下:订单可以取消、可以即将处理、但是没有送达;同理订单已发送状态下:订单不可以取消、订单已经处理、订单即将送达。

我们可以发现状态模式和策略模式非常像,它们其实都是解决了多个if_else的情况。

状态模式遵循哪些设计原则:

1、单一职责原则(SRP):每个状态都有一个明确定义的职责,它只负责管理对象在特定状态下的行为。

2、开闭原则(OCP):状态模式使得添加新状态或修改现有状态的行为变得简单,而无需修改现有的代码。

3、里氏替换原则(LSP):状态对象可以替代彼此,因为它们都实现了相同的接口或基类。

状态模式的优点包括:

1、代码结构清晰:将对象的不同状态封装到独立的类中,使得代码结构更加清晰、易于理解和维护。

2、支持开闭原则:通过添加新的状态类或修改现有状态类的行为,可以方便地扩展和修改对象的行为,而不会影响其他代码。

3、消除了冗余的条件语句:状态模式将状态转换逻辑从客户端代码中移除,这样客户端代码不再需要大量的条件语句来处理不同状态下的行为。

4、提供了一种简洁的方式来配置对象的状态流转:状态模式将对象的状态流转逻辑集中在状态类中,使得状态的变化更加可见和易于管理。

缺点:

1、引入了多个状态类:使用状态模式会引入多个状态类,增加了系统中的类的数量。

2、可能增加代码复杂性:在某些情况下,状态模式可能会增加代码的复杂性,特别是当有大量的状态和状态转换时。

  • 24
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个简单的状态模式示例: ```C #include <stdio.h> // 状态接口 typedef struct State State; struct State { void (*handle)(State*); }; // 具体状态A typedef struct StateA StateA; struct StateA { State state; // 继承自状态接口 int count; // 计数器 }; void StateA_handle(State* super) { StateA* self = (StateA*) super; // 获取自身 printf("这是状态A,当前计数:%d\n", self->count++); } StateA* StateA_new() { StateA* self = (StateA*) malloc(sizeof(StateA)); // 分配内存 self->state.handle = StateA_handle; // 设置状态处理函数 self->count = 0; // 初始化计数器 return self; } // 具体状态B typedef struct StateB StateB; struct StateB { State state; // 继承自状态接口 int count; // 计数器 }; void StateB_handle(State* super) { StateB* self = (StateB*) super; // 获取自身 printf("这是状态B,当前计数:%d\n", self->count++); if (self->count == 3) { // 转移状态 free(self); // 释放内存 self = StateA_new(); // 创建新状态对象 } } StateB* StateB_new() { StateB* self = (StateB*) malloc(sizeof(StateB)); // 分配内存 self->state.handle = StateB_handle; // 设置状态处理函数 self->count = 0; // 初始化计数器 return self; } // 环境类 typedef struct Context { State* state; // 当前状态 } Context; Context* Context_new() { Context* self = (Context*) malloc(sizeof(Context)); // 分配内存 self->state = (State*) StateB_new(); // 初始化状态为B return self; } void Context_request(Context* self) { self->state->handle(self->state); // 调用当前状态的处理函数 } // 测试程序 int main() { Context* context = Context_new(); // 创建环境对象 for (int i = 0; i < 5; i++) { // 循环调用状态处理函数 Context_request(context); } free(context->state); // 释放内存 free(context); return 0; } ``` 运行结果如下: ``` 这是状态B,当前计数:0 这是状态B,当前计数:1 这是状态B,当前计数:2 这是状态A,当前计数:0 这是状态A,当前计数:1 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值