模式C++实现(4)之状态模式(State Pattern)"/>
23中设计模式C++实现(4)之状态模式(State Pattern)
简述:
状态模式又叫做有限状态机。适应场景:我们的对象有多种状态,单对象同一时刻只能保持某一种状态,并当内部变量或者内部变量变化时,我们的对象会在这些状态中变换。
UML结构图
- Context(上下文):定义一个与 Client 交互的接口。它维护对 ConcreteState 对象的引用,可以用该对象来定义当前状态。
- State(抽象状态):定义接口,来声明每个 ConcreteState 应该做什么。
- ConcreteState(具体状态):为 State 中定义的方法提供实现。
在上图中,需要特别注意的是红色的虚线箭头。如果没有这个红色的虚线箭头,你会发现,这个结构图与策略模式的结构图一模一样。我查了很多资料也都没有这个红色的虚线箭头,然而这个红色的虚线箭头才是状态模式的关键所在。这个红色虚线箭头表示的意思是,ConcreteState是依赖于Context的,也就是说,具体的状态是依赖于对象的。具体的体现是,ConcreteState的构造函数需要传入Context的指针作为参数的。
优点
- 避免了大量使用switch/case 、if/else。如果添加新的状态时只需要添加新的状态类,而不需要修改原来的代码,符合开放封闭原则。
- 每个状态的功能,都放在这个状态类中,各个状态类之间低耦合、高内聚,符合单一职责原则。
缺点
- 如果状态有很多,将会创建很多类,加大了编程难度。
例子
在ATM上取钱时候,屏幕显示会跟进我们的操作来不断改变状态。我们来模拟其中的四个状态。
// context.h
#ifndef CONTEXT_H
#define CONTEXT_H#include "concrete_state.h"class ATMMachine
{
private:State* Now_State;
public:ATMMachine();~ATMMachine();void SetState(State* New_State);void Request();
};#endif // CONTEXT_H#pragma once
//context.cpp
#include "concrete_state.h"
#include "context.h"ATMMachine::ATMMachine()
{this->Now_State = new InsertYourCard_State(this);
}ATMMachine::~ATMMachine()
{delete Now_State;
}void ATMMachine::SetState(State* New_State)
{Now_State = New_State;
}void ATMMachine::Request()
{Now_State->handle();
}
上面是context.cpp和context.h的代码。我们用这个来定义一个ATMMachine类
// state.h
#ifndef STATE_H
#define STATE_Hclass State
{
public:virtual ~State() { }virtual void handle() = 0;
};#endif
上面是state.h定义了状态的基类。
// concrete_state.h
#ifndef CONCRETE_STATE_H
#define CONCRETE_STATE_H#include "state.h"
#include "context.h"class ATMMachine;
class PutinNumber_State;class PutinNumber_State : public State
{
public:PutinNumber_State(ATMMachine* p_ATMMachine);~PutinNumber_State() { }void handle();private:ATMMachine* this_ATMMachine;
};class InsertYourCard_State : public State
{
public:InsertYourCard_State(ATMMachine* p_ATMMachine);~InsertYourCard_State() { }void handle();
private:ATMMachine* this_ATMMachine;
};class Home_State : public State
{
public:Home_State(ATMMachine* p_ATMMachine);~Home_State() { }void handle();
private:ATMMachine* this_ATMMachine;
};class WithDraw_State : public State
{
public:WithDraw_State(ATMMachine* p_ATMMachine);~WithDraw_State() { }void handle();
private:ATMMachine* this_ATMMachine;
};#endif // CONCRETE_STATE_H#pragma once
// concrete_state.cpp
#include<iostream>
#include "concrete_state.h"
#include "state.h"//状态:请输入密码
PutinNumber_State::PutinNumber_State(ATMMachine* p_ATMMachine) : this_ATMMachine(p_ATMMachine) { }
void PutinNumber_State::handle()
{int i;std::cout << "请输入您的密码" << std::endl;std::cin >> i;if (i == 100){State* Next_State = new Home_State(this_ATMMachine);this_ATMMachine->SetState(Next_State);delete this;}else{std::cout << "密码错误!!!" << std::endl;}
}//状态:请插入卡
InsertYourCard_State::InsertYourCard_State(ATMMachine* p_ATMMachine) : this_ATMMachine(p_ATMMachine) { }
void InsertYourCard_State::handle()
{int i;std::cout << "请插入您的银行卡" << std::endl;std::cout << "如果银行卡已经插入完毕,请按“1”" << std::endl;std::cin >> i;if (i == 1){State* Next_State = new PutinNumber_State(this_ATMMachine);this_ATMMachine->SetState(Next_State);delete this;}
}//状态:首页
Home_State::Home_State(ATMMachine* p_ATMMachine) : this_ATMMachine(p_ATMMachine) { }
void Home_State::handle()
{int i;std::cout << "进入首页" << std::endl;std::cout << "退卡请按“1" << std::endl;std::cout << "取款请按“2" << std::endl;std::cin >> i;if (i == 1){State* Next_State = new InsertYourCard_State(this_ATMMachine);this_ATMMachine->SetState(Next_State);std::cout << "卡已退出" << std::endl;delete this;}else if (i == 2){State* Next_State = new WithDraw_State(this_ATMMachine);this_ATMMachine->SetState(Next_State);delete this;}
}//状态:取款
WithDraw_State::WithDraw_State(ATMMachine* p_ATMMachine) : this_ATMMachine(p_ATMMachine) { }
void WithDraw_State::handle()
{int i;std::cout << "请输入取款金额" << std::endl;std::cin >> i;std::cout << "已取出金额" << i << "元人民币" << "即将返回首页" << std::endl;State* Next_State = new Home_State(this_ATMMachine);this_ATMMachine->SetState(Next_State);delete this;
}
上面是concrete_state.h和concrete_state.cpp文件,定义了四个状态。
#include <iostream>
#include "context.h"int main()
{ATMMachine my_ATMMachine;while (1){my_ATMMachine.Request();}std::cout << "Hello World!\n";
}
上面是主函数,只需要循环的调用Request()就行啦。
运行结果:
请插入您的银行卡
如果银行卡已经插入完毕,请按“1”
1
请输入您的密码
100
进入首页
退卡请按“1
取款请按“2
2
请输入取款金额
1000
已取出金额1000元人民币即将返回首页
进入首页
退卡请按“1
取款请按“2
1
卡已退出
请插入您的银行卡
如果银行卡已经插入完毕,请按“1”
更多推荐
23中设计模式C++实现(4)之状态模式(State Pattern)
发布评论