设计模式之状态模式(思想)

2023-11-06

设置模式之状态模式

在这里插入图片描述

上图学过网络的同学应该都比较清楚吧,这是一张TCP状态转换图,只要理解上图,那么对状态模式也就很容易理解啦。

状态模式的意图

​ 允许一个对象在其内部状态改变时改变它的行为。简单的说就是:一个人他的外表没有改变,但是他内在的心里状态发生了改变,那他之后的行为就像变了一个人似的;就好比,一个帅哥在追女神的时候,内心无比激动,“舔狼”本色尽显,这时候他的行为时,说话细声细语,对人关怀备至;然而女神的屌丝男友来了,那这个时候,帅哥内心有起伏变化了,行为变得粗鲁无礼,说话也是粗声粗语;人还是那个人,但是内心的状态变化让他的行为举止变了,当然状态的变化时需要一些触发的,下面我们来看看状态模式的细节吧。

状态模式的动机

​ 一个网络连接的类TCPConnection,这个TCPConnection对象的状态处于若干不同状态之一:连接已建立(Established),正在监听(Listening),连接已关闭(Closed)等等。当一个TCPConnection对象收到其他对象请求时,它会根据当前状态做出不同的反应。

​ 这一模式的关键思想是引入了一个称为TCPState的抽象类来表示网络的连接状态。TCPState类为各表示不同的操作状态的子类声明了一个公共接口。

状态模式的使用场景

  • 一个对象的行为取决于它的状态,它必须在运行时根据状态改变它的行为。
  • 一个操作中含有庞大的多分支条件语句,且这些分支依赖于该对象的状态。

状态模式的结构

在这里插入图片描述

Context(环境,如TCP Connection)

​ 定义用户感兴趣的接口。

​ 维护一个ConcreteState子类的实例,这个实例表示当前状态。

State(状态,如TCPState)

​ 定义一个接口以封装与Context的一个特定状态相关的行为。

ConcreteState subClasses(具体状态类,如TCPEstablished,TCPClosed)

​ 每一个子类实现一个Context的一个状态相关的行为。

示例代码(不可运行)

/* 头文件 */
class TCPState;

class TCPConnection {
public:
	TCPConnection();		/* 构造函数 */

	/* 操作 */
	void ActiveOpen();
	void PassiveOpen();
	void Close();
	void Send();
	void Acknowledge();
	void Synchronize();

	void ProcessOctet(TCPOctetStream*);
private:
	friend class TCPState;			/* 友元类 */
	void ChangeState(TCPState*);
private:
	TCPState* _state;				/* 状态 */
};

/* 状态类,最重要的类,主要是用来表示TCPConnection的状态的类 */
/* 这里的状态转换都是通过具体类内部进行的转换,不需要TCPConnection来维持 */
class TCPState {
public:
	virtual void Transmit(TCPConnection*, TCPOctetStream*);
	virtual void ActiveOpen(TCPConnection*);
	virtual void PassiveOpen(TCPConnection*);
	virtual void Close(TCPConnection*);
	virtual void Synchronize(TCPConnection*);
	virtual void Acknowledge(TCPConnection*);
	virtual void Send(TCPConnection*);
protected:
	void ChangeState(TCPConnection*, TCPState*);
};

class TCPOctetStream {};

/* 具体的状态类 */
class TCPClosed : public TCPState {
public:
	static TCPState* Instance();
	virtual void ActiveOpen(TCPConnection*);
	virtual void PassiveOpen(TCPConnection*);
};

class TCPEStablished : public TCPState {
public:
	static TCPState* instance();
	virtual void Transmit(TCPConnection*, TCPOctetStream*);
	virtual void Close(TCPConnection*);
};

class TCPListen : public TCPState {
public:
	static TCPState* Instance();
	virtual void send(TCPConnection*);
};
/* TCPConnection.cpp */
#include "TCPConnection.h"
#include "TCPClosed.h"
#include "TCPEstablished.h"
#include "TCPListen.h"

#include <iostream>

TCPConnection::TCPConnection() {
	_state = TCPClosed::Instance();
}

void TCPConnection::ChangeState(TCPState* s) {
	_state = s;
}

void TCPConnection::ActiveOpen() {
	_state->ActiveOpen(this);
}

void TCPConnection::PassiveOpen() {
	_state->PassiveOpen(this);
}

void TCPConnection::Close() {
	_state->Close(this);
}

void TCPConnection::Acknowledge() {
	_state->Acknowledge(this);
}

void TCPConnection::Synchronize() {
	_state->Synchronize(this);
}

void TCPConnection::Send() {
	_state->Send(this);
}

void TCPConnection::ProcessOctet(TCPOctetStream* o) {
	std::cout << "processOctet" << std::endl;
}

/* TCPState.cpp */
#include "TCPState.h"

void TCPState::Transmit(TCPConnection*, TCPOctetStream*) {}

void TCPState::ActiveOpen(TCPConnection*) {}
void TCPState::PassiveOpen(TCPConnection*) {}
void TCPState::Close(TCPConnection*) {}
void TCPState::Synchronize(TCPConnection*) {}

void TCPState::ChangeState(TCPConnection* t, TCPState* s) {
	t->ChangeState(s);
}

/* 具体状态类的cpp */
/* 这里的具体实例的Instance()函数都是使用单例模式来实现的 */
void TCPClosed::ActiveOpen(TCPConnection *t){
    ChangeState(t,TCPEstablished::Instance());
}

void TCPClosed::PassiveOpen(TCPConnection* t){
    ChangeState(t,TCPListen::Instance());
}

void TCPEstablished::Close(TCPConnection *t){
    ChangeState(t,TCPCLose::Instance());
}

void TCPEstablished::Transmit(TCPConnection* t, TCPOctetStream* o){
    t->processOctet(o);
}

void TCPListen::Send(TCPConnection *t){
    ChangeState(t,TCPEstablished::Instance());
}

上面代码锁表示的状态转换图:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

设计模式之状态模式(思想) 的相关文章

随机推荐

  • 参考文献期刊首字大写_sci论文参考文献格式

    学术论文的写作都离不开参考文献的引用与借鉴 参考文献的引用与借鉴可以让我们的文章更具可读性 也更具权威性与科学性 所以学术界对参考文献的引用有着明确的格式要求 凡是引用他人的文献都要在文章中做相应标注 这对原作者来说也是一种权利的保护 参考
  • 【OLED驱动】:stm32F103的四线模拟IIC驱动的0.96寸OLED屏幕显示数字,字母,汉字,图片的例程

    文章目录 前言 一 四线OLED是什么 二 IIC原理 1 四线0 96寸OLED是IIC驱动来实现显示 2 IIC协议的OLED屏幕 3 STM32驱动代码 4 IIC使用代码 总结 前言 最近在做一个开源方案 平衡车 即将开源硬件和软件
  • C++报错不允许使用不完整的类型

    include pch h include
  • #define _CRT_SECURE_NO_WARNINGS 1问题

    文章目录 前言 一 为什么用了scanf strcyp strlen strcat等函数会报错 二 操作步骤 1 下载notepad 2 修改 总结 前言 当我们的代码出现这样的报错时 不要慌张 应该是你用了scanf strcyp str
  • Merkle Tree(默克尔树)算法解析

    Merkle Tree 默克尔树 算法解析 1 Merkle Tree概念 Merkle Tree 通常也被称作Hash Tree 顾名思义 就是存储hash值的一棵树 Merkle树的叶子是数据块 例如 文件或者文件的集合 的hash值
  • 记一次jvm项目调优

    问题描述 运维一直说 fy core 项目这个项目每天都会发生多次full gc full gc 会停顿600ms左右 理论上生产环境不允许发生full gc 所以决定把full gc都优化掉 以下是该grafana对应的资源表现 可以看出
  • react生命周期componentDidMount中设置setState在esIint报错

    react生命周期componentDidMount中设置setState在esIint报错 项目背景 由于需要在页面渲染出来的时 对state中的数据进行初始化并需要出发render重绘 componentDidMount let sel
  • 5G“邂逅”云计算,运营商云网融合大势所趋

    近几年 国内运营商纷纷发力布局云计算市场 力求在云领域打造出自己的地盘 近期 中国电信天翼云与中科曙光战略合作 双方将共同探索在 5G 云 领域的建设 去年8月中国移动在苏州成立中国移动云能力中心 中国联动也于去年年底发布沃云云计算战略 而
  • navicat使用触发器在插入记录修改某个字段的值

    最近项目遇到了一个问题 查用户的某些字段有NULL会报错 所以想在注册的时候用的触发器提前设置一个默认值 避免空指针 先在本地建一个测试表t 1 就给三个基本字段 然后右击表选择设计表找到 触发器 开始编辑 现在的写法是正确的 我之前是这样
  • B站马士兵python入门基础版详细笔记(4)

    前言 这篇文章是B站学习python入门基础班的视频的第四章内容 主要讲述的是if else语句 但是不包括循环结构 循环结构在下一章笔记中有记叙 一 顺序结构 什么是顺序结构呢 比如说 把大象装冰箱需要分几步 print 程序开始 pri
  • 数模比赛提分tips

    1 对于模型的建立和求解 这一部分是文章的重点 要特别突出你的创造性的工作 在这部分写作需要注意的事项有 一定要有分析 而且分析应在所建立模型的前面 一定要有明确的模型 不要让别人在你的文章中去找你的模型 关系式一定要明确 思路要清晰 易读
  • 指针进阶(三)

    指针进阶 三 指针习题组 01 int main int a 5 1 2 3 4 5 int ptr int a 1 printf d d a 1 ptr 1 return 0 运行结果 原因 这里a是数组名 存放的是数组的首地址 a是整个
  • pip install tensorflow报错ERROR: Could not find a version that satisfies the requirement tensorflow (f

    这里写目录标题 报错内容 解决方法 其他方法 原因分析 报错内容 pip3 install tensorflow 输入上述命令安装tensorflow后出现下面的报错 ERROR Could not find a version that
  • chrome浏览器被hao123劫持如何解决?

    那天上班 打开电脑点开chrome浏览器 首页出现的是我熟悉的谷歌搜索页面 可是很快右边又打开了一个页面 123 hao234 com 这个流氓网站就这个这么不请自来了 而且之后我用尽了网上各种办法都弄不走 各种无效方法 1 绑定自己的主页
  • 背包九讲--混合背包、分组背包、资源分配背包、背包方案总数

    混合背包 混合背包 问题描述 一个旅行者有一个最多能用V公斤的背包 现在有n件物品 它们的重量分别是W1 W2 Wn 它们的价值分别为C1 C2 Cn 有的物品只可以取一次 01背包 有的物品可以取无限次 完全背包 有的物品可以取的次数有一
  • hive基础(二) hive操作大全

    目录 注 只是为了以后忘了 好翻 做个总结 一 hive 操作 1 hive e 2 hive f 3 查看在hive中输入的所有历史命令 4 hive运行日志修改 二 hive参数配置 三 hive数据类型 基本数据类型 集合数据类型 1
  • PHP与MySQL程序设计 学习笔记 第八章 错误和异常处理

    error reporting函数确定报告的敏感级别 共有16个不同级别 这些级别的任何组合都是有效的 error reporting函数使用 字符表示逻辑操作符NOT error reporting E ALL E STRICT 希望报告
  • python两列表对应元素求和

    一种方法是循环 但是有简便方法 用numpy import numpy as np list1 1 2 3 4 list2 1 2 3 4 a array np array list1 b array np array list2 c ar
  • matlab安装好 启动总是闪退_win10系统启动matlab出现闪退的处理技巧

    电脑操作系统在使用的时候经常会被一些问题所困扰 例如很多用户都遇见过win10系统启动matlab出现闪退的问题 大部分用户如果第一次碰到win10系统启动matlab出现闪退的现象 因此大伙都会不知所措 怎么才可以完善的治理win10系统
  • 设计模式之状态模式(思想)

    设置模式之状态模式 上图学过网络的同学应该都比较清楚吧 这是一张TCP状态转换图 只要理解上图 那么对状态模式也就很容易理解啦 状态模式的意图 允许一个对象在其内部状态改变时改变它的行为 简单的说就是 一个人他的外表没有改变 但是他内在的心