设计模式---状态变化模式之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,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第六个模式--状 ...
随机推荐
- BZOJ3790神奇项链——manacher+贪心
题目描述 母亲节就要到了,小 H 准备送给她一个特殊的项链.这个项链可以看作一个用小写字 母组成的字符串,每个小写字母表示一种颜色.为了制作这个项链,小 H 购买了两个机器.第一个机器可以生成所有形式 ...
- 第四十一天 socker server和 event
今日内容 1.基于TCP的socketserver 2.基于UDP的socketserver 3.event 一.TCP的socketserver #服务器 import socketserver f ...
- 洛谷3822 [NOI2017] 整数 【线段树】【位运算】
题目分析: 首先这题的询问和位(bit)有关,不难想到是用线段树维护位运算. 现在我们压32位再来看这道题. 对于一个加法操作,它的添加位置可以得到,剩下的就是做不超过32的位移.这样根据压位的理论. ...
- Marriage Match II HDU - 3081(二分权值建边)
题意: 有编号为1~n的女生和1~n的男生配对 首先输入m组,a,b表示编号为a的女生没有和编号为b的男生吵过架 然后输入f组,c,d表示编号为c的女生和编号为d的女生是朋友 进行配对的要求满足其一即 ...
- 【XSY2703】置换 数学 置换 DP
题目描述 对于置换\(p\),定义\(f(p)\)为最小的正整数\(k\),使得\(p^k\)为恒等置换. 你需要求对于所有的\(n\)元素置换\(p\),\(f^2(p)\)的平均值. \(n\le ...
- Gym - 101848C Object-Oriented Programming (树链剖分+线段树+动态开点)
C. Object-Oriented Programming time limit per test 3.0 s memory limit per test 1024 MB input standar ...
- Dynamic CRM 2015学习笔记(4)修改开发人员资源(发现服务、组织服务和组织数据服务)url地址及组织名
在azure vm上安装了CRM 2015后 Dynamic CRM 2015学习笔记(1)Azure 上安装 CRM 2015, 发现了一个问题,那就是在设置 ->自定义项 –> 开发人 ...
- cf1061E Politics (费用流)
看到数据范围,考虑网络流..但考的时候完全不知道怎么建图 考虑流量表示选的点个数,费用表示选点的收益,跑最大费用最大流 那么我用一个点x表示某树中的询问点x,刨去它子孙询问点的子树后的子树 对于树1, ...
- mysql 替换字符中部分字符,替换使用指定字符
update table_name set name= replace(name,'我是','是');
- ACM-ICPC 2018 南京赛区网络预赛 L题(分层最短路)
题目链接:https://nanti.jisuanke.com/t/31001 题目大意:给出一个含有n个点m条边的带权有向图,求1号顶点到n号顶点的最短路,可以使<=k条任意边的权值变为0. ...