设计模式---状态变化模式之state状态模式(State)
前提:状态变化模式
在组建构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”模式为这一个问题提供了一种解决方案。
典型模式
状态模式:State
备忘录模式:Memento
一:State状态模式
(一)概念
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类
状态模式主要解决的是当控制一个对象状态的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简化。
(二)动机
在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态支持的行为就可能会完全不同。
如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?
我们将状态逻辑和动态实现进行分离操作
(三)代码讲解
1.原代码
enum NetworkState //状态枚举
{
Network_Open,
Network_Close,
Network_Connect,
}; class NetworkProcessor{ NetworkState state; public:
void Operation1(){ //多种操作模式
if (state == Network_Open){ //根据当前网络状态,修改下一步的网络状态 //**********
state = Network_Close;
}
else if (state == Network_Close){ //..........
state = Network_Connect;
}
else if (state == Network_Connect){ //$$$$$$$$$$
state = Network_Open;
}
} public void Operation2(){ if (state == Network_Open){ //**********
state = Network_Connect;
}
else if (state == Network_Close){ //.....
state = Network_Open;
}
else if (state == Network_Connect){ //$$$$$$$$$$
state = Network_Close;
} } public void Operation3(){ }
};
我们发现if...else..的使用同strategy策略模式十分相像,动态考虑,以后这些状态会不会出现变化,例如:出现Network_wait状态后如何变化?
违背了开闭原则,依循strategy模式经验,抽象基类提出
2.改进代码,将基类抽出
class NetworkState{
public:
NetworkState* pNext;
virtual void Operation1()=;
virtual void Operation2()=;
virtual void Operation3()=;
virtual ~NetworkState(){}
};
class OpenState :public NetworkState{
static NetworkState* m_instance; //单例模式,因为各个状态只需要一个
public:
static NetworkState* getInstance(){
if (m_instance == nullptr) {
m_instance = new OpenState();
}
return m_instance;
}
void Operation1(){
//********** 处理逻辑和上面还是一致的
pNext = CloseState::getInstance();
}
void Operation2(){
//..........
pNext = ConnectState::getInstance();
}
void Operation3(){
//$$$$$$$$$$
pNext = OpenState::getInstance();
}
};
class CloseState:public NetworkState{ }
//...多个状态对象
把状态相关的操作,全部编码到一个状态对象中
class NetworkProcessor{
NetworkState* pState; //放的不再是枚举类型,而是状态对象
public:
NetworkProcessor(NetworkState* pState){
this->pState = pState;
}
void Operation1(){
//...
pState->Operation1();
pState = pState->pNext;
//...
}
void Operation2(){
//...
pState->Operation2();
pState = pState->pNext;
//...
}
void Operation3(){
//...
pState->Operation3();
pState = pState->pNext;
//...
}
};
是哪种状态就调用哪种操作
我们只需要关心状态自身的变化,而不需要去看状态和NetworkProcessor之间的关系
//扩展,解耦合
class WaitState:public NetworkState{ }
(四)模式定义
允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。
——《设计模式》GoF
(五)类图(结构)
state和strategy模式非常像,策略模式是一个行为,状态模式可以是一个也可以是多个行为,当是一个行为是和策略模式基本相同

(六)要点总结
1.State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时, 切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。
只需要关心操作之后的下一个状态即可,而不需要去想更多耦合情况
2.为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的——即要么彻底转换过来,要么不转换。
3.如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。
单例模式,节省开销
(七)案例演示 (一)
1.state基类
class State
{
public:
State* pNext;
virtual void doSomething() = ;
virtual ~State(){}
};
2.具体状态类
class Study :public State
{
private:
Study(){}
Study(const Study& obj){}
Study& operator=(const Study& obj){}
public:
static State* m_instance; static State* getInstance()
{
if (m_instance == nullptr) {
m_instance = new Study();
}
return m_instance;
} virtual void doSomething();
}; class EatFood :public State
{
private:
EatFood(){}
EatFood(const EatFood& obj){}
EatFood& operator=(const EatFood& obj){}
public:
static State* m_instance; static State* getInstance()
{
if (m_instance == nullptr) {
m_instance = new EatFood();
}
return m_instance;
} virtual void doSomething();
}; class Sleep :public State
{
private:
Sleep(){}
Sleep(const Sleep& obj){}
Sleep& operator=(const Sleep& obj){}
public:
static State* m_instance; static State* getInstance()
{
if (m_instance == nullptr) {
m_instance = new Sleep();
}
return m_instance;
} virtual void doSomething();
}; State* Study::m_instance = NULL; //静态成员必须在外部声明
State* Sleep::m_instance = NULL;
State* EatFood::m_instance = NULL;
//因为存在各个类之间想回调用,所以将该函数定义写在所有类声明后面
void Study::doSomething()
{
cout << "I will to study" << endl;
pNext = Sleep::getInstance();
} void Sleep::doSomething()
{
cout << "I will sleep" << endl;
pNext = EatFood::getInstance();
} void EatFood::doSomething()
{
cout << "I will eat food" << endl;
pNext = Study::getInstance();
}
3.客户实现
class Student
{
State* pState;
public:
Student(State* ps) :pState(ps){} void dosSomething()
{
pState->doSomething();
pState = pState->pNext;
}
};
4.状态演示
int main()
{
State* st = Sleep::getInstance();
Student* stu = new Student(st);
stu->dosSomething();
stu->dosSomething();
stu->dosSomething();
system("pause");
return ;
}

(八)案例演示(二)
#include <iostream>
#include <string>
#include "state.h"
using namespace std;
#include <iostream>
using namespace std; class Worker; class State
{
public:
virtual void doSomeThing(Worker* w) = ;
}; class Worker
{
private:
int m_hour;
State* m_currState; //对象当前状态
public:
Worker(); void setHour(int hour)
{
m_hour = hour;
} int getHour()
{
return m_hour;
} State* getCurrState()
{
return m_currState;
} void setCurrentState(State* state)
{
m_currState = state;
} void doSomeThing()
{
m_currState->doSomeThing(this);
}
}; class State1 :public State
{
public:
static State* m_Instance; static State* getInstance()
{
if (m_Instance == NULL)
{
m_Instance = new State1();
}
return m_Instance;
} void doSomeThing(Worker* w);
}; class State2 :public State
{
public:
static State* m_Instance; static State* getInstance()
{
if (m_Instance==NULL)
{
m_Instance = new State2();
}
return m_Instance;
} void doSomeThing(Worker* w);
}; State* State1::m_Instance = NULL;
State* State2::m_Instance = NULL; void State1::doSomeThing(Worker* w)
{
if (w->getHour() == || w->getHour() == )
{
cout << "eat food" << endl;
}
else
{
w->setCurrentState(State2::getInstance());
w->getCurrState()->doSomeThing(w);
}
} void State2::doSomeThing(Worker* w)
{
if (w->getHour() == || w->getHour() == )
{
cout << "work" << endl;
}
else
{
w->setCurrentState(State1::getInstance()); //恢复到初始状态
cout << "current time don`t know to do something" << endl;
}
} Worker::Worker()
{
m_currState = new State1();
} void main()
{
Worker* w1 = new Worker();
w1->setHour();
w1->doSomeThing(); w1->setHour();
w1->doSomeThing(); delete w1;
system("pause");
return;
}

设计模式---状态变化模式之state状态模式(State)的更多相关文章
- 设计模式 ( 十八 ):State状态模式 -- 行为型
1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到.然后使用if... ellse语句来做状态判断来进行不同情况的处理.但是对 ...
- 设计模式21:State 状态模式(行为型模式)
State 状态模式(行为型模式) 动机(Motivation) 在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生变化,比如文档处于只读状态,其支持的行为和读写状态的行为就可能完全不同. ...
- C++设计模式-State状态模式
State状态模式作用:当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. UML图如下: State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为. ...
- State 状态模式
简介 状态模式允许一个对象在其内部[状态]改变的时候改变其[行为].这个对象看上去就像是改变了它的类一样. 用一句话来表述,状态模式把所研究的对象的[行为]包装在不同的[状态对象]里,[每一个状态对象 ...
- State 状态模式 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 19、State 状态模式
“人有悲欢离合,月有阴晴圆缺”,包括人在内,很多事物都具有多种状态,而且在不同状态下会具有不同的行为,这些状态在特定条件下还将发生相互转换.就像水,它可以凝固成冰,也可以受热蒸发后变成水蒸汽,水可以流 ...
- State状态模式
1.简介 在日常开发中,某些对象的状态如果发生改变,对应的行为也将发生改变,那么如何在运行时根据对象的状态动态的改变对象的行为,同时不产生紧耦合关系(即使用if else或者swith所带来的紧耦合关 ...
- 设计模式之第21章-状态模式(Java实现)
设计模式之第21章-状态模式(Java实现) “what are you 干啥了?怎么这么萎靡不振?”“昨晚又是补新番,又是补小笼包,睡得有点晚啊.话说杨过的那个雕兄真是太好了,每天给找蛇胆,又陪练武 ...
- C#设计模式学习笔记:(18)状态模式
本笔记摘抄自:https://www.cnblogs.com/PatrickLiu/p/8032683.html,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第六个模式--状 ...
随机推荐
- [Codeforces757G]Can Bash Save the Day?——动态点分治(可持久化点分树)
题目链接: Codeforces757G 题目大意:给出一棵n个点的树及一个1~n的排列pi,边有边权,有q次操作: 1 l r x 求 $\sum\limits_{i=l}^{r}dis(p_{i} ...
- pycharm2019+破解补丁
事先声明,由于本人的pycharm已经装好,故部分图片来自网络,转载请注明地址 这篇博文以前是2018版本 后来换电脑重装时发现失效了 索性装的2019版本 具体步骤可以参考下面的删除线,新的补丁和激 ...
- 轮询、长轮询、websock
引入 Web端即时通讯技术:即时通讯技术简单的说就是实现这样一种功能:服务器端可以即时地将数据的更新或变化反应到客户端,例如消息即时推送等功能都是通过这种技术实现的.但是在Web中,由于浏览器的限制, ...
- C - A Simple Problem with Integers POJ - 3468 线段树模版(区间查询区间修改)
参考qsc大佬的视频 太强惹 先膜一下 视频在b站 直接搜线段树即可 #include<cstdio> using namespace std; ; int n,a[maxn]; stru ...
- The Embarrassed Cryptographer POJ - 2635 同余模+高精度处理 +线性欧拉筛(每n位一起处理)
题意:给出两数乘积K(1e100) 和 一个数L(1e6) 问有没有小于L(不能等于)的素数是K的因数 思路:把数K切割 用1000进制表示 由同余模公式知 k%x=(a*1000%x+b* ...
- Scrapy爬取伯乐在线文章
首先搭建虚拟环境,创建工程 scrapy startproject ArticleSpider cd ArticleSpider scrapy genspider jobbole blog.jobbo ...
- Win10 GodMode
Win10 GodMode 文件夹命名示例: GodMode.{ED7BA470-8E54-465E-825C-99712043E01C} {ED7BA470-8E54-465E-825C-99712 ...
- MT【290】内外圆求三角最值
求$\sqrt{\dfrac{5}{4}-\sin x}+2\sqrt{\dfrac{9}{4}+\cos x-\sin x}$的最小值. 提示:$\sqrt{\dfrac{5}{4}-\sin x} ...
- MT【272】更大的视野,更好的思路.
已知$f(x)=\sum\limits_{k=1}^{2017}\dfrac{\cos kx}{\cos^k x},$则$f(\dfrac{\pi}{2018})=$_____ 分析:设$g(x)=\ ...
- pycharm 2016.1.4 软件注册码生成
昨天电脑忽然坏了,没办法只能电脑重做系统,最让我头疼的是面对新电脑的软件安装和配置..... 由于之前电脑很久没有升级过ide,所以pycharm一直停留在2016.1.4的版本,当我打开pychar ...