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_H

class 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”

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值