设计模式---状态变化模式之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,记录一下学习过程以备后续查用. 一.引言 今天我们要讲行为型设计模式的第六个模式--状 ...
随机推荐
- python 文件下载
为了演示urllib3的使用,我们这里将会从一个网站下载两个文件.首先,需要导入urllib3库: import urllib3 这两个文件的源url为: url1 = 'http://earthqu ...
- JDK 与TOMCAT的安装详解
转自:http://www.jb51.net/article/51909.htm Tomcat7.0.22在Windows下详细配置过程 一.JDK1.7安装 1.下载jdk,下载地址:http:// ...
- 【XSY1529】小Q与进位制 分治 FFT
题目大意 小Q发明了一种进位制,每一位的变化范围是\(0\)~\(b_i-1\),给你一个这种进位制下的整数\(a\),问你有多少非负整数小于\(a\).结果以十进制表示. \(n\leq 1 ...
- hdu 4825 Xor Sum (01 Trie)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4825 题面: Xor Sum Time Limit: 2000/1000 MS (Java/Others) ...
- MT【292】任意存在求最值
已知向量$\textbf{a},\textbf{b}$满足:$|\textbf{a}|=|\textbf{b}|=1,\textbf{a}\cdot\textbf{b}=\dfrac{1}{2},\t ...
- 「UVA10766」Organising the Organisation(生成树计数)
BUPT 2017 Summer Training (for 16) #6C 题意 n个点,完全图减去m条边,求生成树个数. 题解 注意可能会给重边. 然后就是生成树计数了. 代码 #include ...
- js中获取css样式属性值
关于js中style,currentStyle和getComputedStyle几个注意的地方 (1)用js的style只能获取元素的内联样式,内部样式和外部样式使用style是获取不到的.针对css ...
- [FJOI2015]火星商店问题(分治+可持久化)
题目描述 火星上的一条商业街里按照商店的编号1,2 ,…,n ,依次排列着n个商店.商店里出售的琳琅满目的商品中,每种商品都用一个非负整数val来标价.每个商店每天都有可能进一些新商品,其标价可能与已 ...
- 深挖JDK动态代理(一)
最近在研究RPC框架,避免不了的就是在RPC调用中使用最多的则是动态代理的机制了,基于此,我们先来研究一下JDK动态代理 我们先来尝试着编写一下JDK动态代理的代码 1. 由于JDK动态代理是基于接 ...
- Shiro中的Remember me设置
1. 在Spring的相关配置文件中加入如下Remember me管理器配置: <!-- rememberMe管理器 --> <bean id="rememberMeMan ...