设计模式---状态变化模式之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,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第六个模式--状 ...
随机推荐
- PHP——base64的图片转为文件图片
前言 网上很多,真的是有毒吧,一个那么简单至于写的乱七八糟的嘛,醉了. 代码 具体都写注释中了,不懂的可以评论或者私信我 public function upload() { //接收前台的值 $ba ...
- P1403 [AHOI2005]约数研究
原题链接 https://www.luogu.org/problemnew/show/P1403 这个好难啊,求约数和一般的套路就是求1--n所有的约数再一一求和,求约数又要用for循环来判断.... ...
- BZOJ4818 [SDOI2017] 序列计数 【矩阵快速幂】
题目分析: 一个很显然的同类项合并.注意到p的大小最大为100,考虑把模p意义下相同的求出来最后所有的减去没有质数的做矩阵快速幂即可. 代码: #include<bits/stdc++.h> ...
- 洛谷P1047校门外的树题解
题目 此题是一个模拟题,但需要注意的一点就是它的树是从数轴的0开始,所以我们也要从0开始,这样才能实现代码. 代码: #include<iostream> using namespace ...
- 【BZOJ2431】【HAOI2009】逆序对数列 DP
题目大意 问你有多少个由\(n\)个数组成的,逆序对个数为\(k\)的排列. \(n,k\leq 1000\) 题解 我们考虑从小到大插入这\(n\)个数. 设当前插入了\(i\)个数,插入下一个数可 ...
- composer阿里云短信服务不支持传参为数值--为2017年短信接口,2018阿里云有更新http://www.cnblogs.com/q1104460935/p/8916096.html
composer 阿里云短信服务使用 xuying/aliyun_mns 更新到2017年初,不再更新 ){;, ); }; } ; }; }; }} 以下为发送成功返回对象 object(A ...
- jwt实现
<?phpnamespace app\admin\controller;use think\Config;use think\Controller;use think\Request;use t ...
- 「2017 Multi-University Training Contest 1」2017多校训练1
1001 Add More Zero(签到题) 题目链接 HDU6033 Add More Zero 找出最大的k,使得\(2^m-1\ge 10^k\). 直接取log,-1可以忽略不计. #inc ...
- 牛客网noip集训4
T1 (A)[https://www.nowcoder.com/acm/contest/175/A] 给出 l, r, k,请从小到大输出所有在 [l, r] 范围内,能表示为 k 的非负整数次方的所 ...
- 【Tsinsen A1339】JZPLCM (树状数组)
Description 原题链接 给定一长度为\(~n~\)的正整数序列\(~a~\),有\(~q~\)次询问,每次询问一段区间内所有数的\(~LCM~\)(即最小公倍数).由于答案可能很大,输出 ...