一、状态模式

状态模式,允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。它的实现方式和策略模式相似,目的都是对if...else语句进行优化,只不过,策略模式通过外部传入枚举、条件来决定选择哪一种操作方式。策略模式中的枚举、条件相当于状态模式中的状态。状态不需要由外部传入,而是随着自身的操作来自动地变化。

例如类Context 包含以下的流程图,context 有两个方法run 和fallback,四种状态,例如当状态Ready执行一次run操作状态变成了d式,允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。它的实现方式和策略模式相似,目的都是对if...else语句进行优化,只不过,策略模式通过外部传入枚举、条件来决定选择哪一种操作方式。策略模式中的枚举、条件相当于状态模式中的状态。状态不需要由外部传入,而是随着自身的操作来自动地变化。

例如类Context 包含以下的流程图,context 有两个方法run 和fallback,四种状态,例如当状态Ready执行一次run操作状态变成了executing,当再执行run时就变成了完成状态,如果执行fallback就变成了hangup状态。

本例目标是为了展示 2*100  的计算和输出过程。

方法一

enum State{Ready,Executing,Finish,Hangup
}class Context{State state;int result;public:void run(){if(state == Ready){result = 2;state = Executing;}else if(state == Executing){result *=100;state =Finish;}else if(state == Finish){cout<<"result:"<<result;result=0;state =Ready;}else if(state ==Hangup){state = Executing;}}void fallback(){if(state == Ready){state = Ready;result=0;}else if(state == Executing){state =Hangup;}else if(state == Finish){result /=100;state =Executing;}else if(state ==Hangup){state = Ready;result =2;}}
}

当操作方法发生需求变更时,方法一代码这样写影响范围就会覆盖整个流程,代码不易维护,不易扩展。如果增加状态,那么枚举要新增,run方法和fallback方法也要跟者新增,代码会变得越来越臃肿。

方法二:利用状态模式,把枚举变成类对象

enum State{Ready,Executing,Finish,Hangup
}
/********状态类,可用单例模式进行优化***********/
class IState{virtual State oprationRun(Context *)=0;virtual State oprationFallback(Context *)=0;
};
class ReadyState:public IState{
public:virtual State oprationRun(Context * context){context->result=2;return Executing;}virtual State oprationFallback(Context * context){context->result=0;return Ready;}
};
class ExecutingState:public IState{
public:virtual State oprationRun(Context * context){context->result *=100;return Finish;}virtual State oprationFallback(Context * context){return Hangup;}
};
class FinishState:public IState{
public:virtual State oprationRun(Context * context){cout<<"result:"<< context->result;context->result =0;return Ready;}virtual State oprationFallback(Context * context){context->result /=100;return  Executing;}
};
class HangupState:public IState{
public:virtual State oprationRun(Context * context){return Executing;}virtual State oprationFallback(Context * context){context->result=2;return Ready;}
};/*********Context自动地完成操作******************/
class Context{State state;        //状态属性,这个属性变化,操作也会动态地变化IState * iState;    //状态对象int result;
private:
void initIState(){switch(state){case Ready: iState =new ReadyState(); break;case Executing:iState =new ExecutingState(); break;case Finish: iState =new FinishState();  break;case Hangup: iState =new HangupState();  break;Default:....ERROR....}
}public:Context(){state =Ready;result =0;}void run(){initIState();state =iState->oprationRun(this);}void fallback(){initIState();state =iState->oprationFallback(this);}
}

这样的好处就是当变更状态内部操作时,不需要改动Context方法。当新增一个状态时,只需要新增一个状态类和一个映射就可以,不需要变动其他状态方法。这样编码结构清晰,误操作的可能变小,变得更容易维护。

最后调用过程

void main(){Context context; //result =0 ,状态为Readycontext.run(); //result =2 ,状态从Ready变成Executing;context.run(); //result =200 ,状态从Executing变成finish;context.run(); //输出 200 ,状态从finish变成Ready; result =0
}

二、备忘录模式

备忘录模式,在不破坏封装性的前提下,捕获对象内部的状态,并将者着状态放在外部进行保存(比如文件,数据库)。方便以后对象恢复到原先的状态。相当于游戏的存档。

在模式中,具体实现的方式就是新增一个类,用来存储原先对象重要的属性。

继续按照上述例子,新增备忘录类和get/set备忘录方法

enum State{Ready,Executing,Finish,Hangup
}
/********状态类,可用单例模式进行优化***********/
class IState{virtual State oprationRun(Context *)=0;virtual State oprationFallback(Context *)=0;
};
class ReadyState:public IState{
public:virtual State oprationRun(Context * context){context->result=2;return Executing;}virtual State oprationFallback(Context * context){context->result=0;return Ready;}
};
class ExecutingState:public IState{
public:virtual State oprationRun(Context * context){context->result *=100;return Finish;}virtual State oprationFallback(Context * context){return Hangup;}
};
class FinishState:public IState{
public:virtual State oprationRun(Context * context){cout<<"result:"<< context->result;context->result =0;return Ready;}virtual State oprationFallback(Context * context){context->result /=100;return  Executing;}
};
class HangupState:public IState{
public:virtual State oprationRun(Context * context){return Executing;}virtual State oprationFallback(Context * context){context->result=2;return Ready;}
};/*********Context自动地完成操作******************/
class Context{State state;        //状态属性,这个属性变化,操作也会动态地变化IState * iState;    //状态对象int result;
private:
void initIState(){switch(state){case Ready: iState =new ReadyState(); break;case Executing:iState =new ExecutingState(); break;case Finish: iState =new FinishState();  break;case Hangup: iState =new HangupState();  break;Default:....ERROR....}
}public:Context(){state =Ready;result =0;}void run(){initIState();state =iState->oprationRun(this);}void fallback(){initIState();state =iState->oprationFallback(this);}/****创建存档和读取存档*****/ContextMemento createMemento(){return ContextMemento (state,result);}void setMemento(ContextMemento& cm){state = cm.oldstate;result = cm.oldresult;}
}/**********备忘录对象************/
class  ContextMemento{
public: State oldstate;        //状态属性,这个属性变化,操作也会动态地变化int oldresult;ContextMemento (State s, int r){oldstate= s;  oldresult=r;}
} 
void main(){Context context; //result =0 ,状态为Readycontext.run(); //result =2 ,状态从Ready变成Executing;ContextMemento  contextMemento = context.createMemento();context.run(); //result =200 ,状态从Executing变成finish;context.setMemento(contextMemento ); //result =2  状态为 Executingcontext.run();  //result =200 ,状态从Executing变成finish;context.run();//输出 200 ,状态从finish变成Ready; result =0
}

备忘录的目的就是为了存档,现如今,储存/读取对象有更方便的方式。备忘录模式在如今有些过时。更有效的方式可以替代备忘录模式,例如对象序列化,对象编码等。但是备忘录的思想还是没变:

1)不破坏原对象的封装性

2) 获取原对象重要的属性,并对这些属性进行隐藏

设计模式的理解:状态模式(State) 和备忘录模式(Memento)相关推荐

  1. 《JAVA与模式》之备忘录模式

    备忘录模式又叫做快照模式(Snapshot Pattern)或Token模式,是对象的行为模式. 备忘录对象是一个用来存储另外一个对象内部状态的快照的对象.备忘录模式的用意是在不破坏封装的条件下,将一 ...

  2. Android设计模式(十五)--备忘录模式

    在Android中用于保存Activity状态的onSaveInstanceState()和恢复Activity状态的onRestoreInstanceState(), 这样的算不算是一种备忘录模式呢 ...

  3. 23种设计模式C++源码与UML实现--备忘录模式

    备忘录模式 Memento模式也叫备忘录模式,是行为模式之一,它的作用是保存对象内部状态,并在需要的时候(undo/roback)回复对象以前的状态. 应用场景 如果一个对象需要保存状态,并通过und ...

  4. java设计模式-备忘录模式

    备忘录模式详解 备忘录模式又叫作快照模式或Token模式,是一种对象的行为模式.在备忘录模式里,一个备忘录是一个对象,它存储另一个对象(原发器对象)在某个瞬间的内部状态.备忘的目的就是为了以后在需要的 ...

  5. Java设计模式(备忘录模式-解释器模式-状态模式-策略模式-职责链模式)

    Java设计模式Ⅶ 1.备忘录模式 1.1 备忘录模式概述 1.2 代码理解 2.解释器模式 2.1 解释器模式概述 3.状态模式 3.1 状态模式概述 3.2 代码理解 4.策略模式 4.1 策略模 ...

  6. 7、大话设计模式--状态模式 、适配器模式、备忘录模式、组合模式、迭代器模式

    第十六章:无尽加班何时休--状态模式 状态模式 :   优点: 缺点: 所使用的项目是:工作状态 功能: 界面: 设计思路: 收获: 附: 1.概述 在软件开发过程中,应用程序可能会根据不同的情况作出 ...

  7. 设计模式(模板模式,命令模式,备忘录模式)

    目录 模板模式 什么是模板模式? 术语? 什么时候使用模板模式? 模板模式的优点? 模板模式的缺点? 角色? 钩子函数? 注意事项和细节? 什么场景使用模板模式? 案例: 命令模式 什么是命令模式? ...

  8. 23种设计模式之---备忘录模式

    前言 网上搜索备忘录设计模式,基本上均是在一个GoF,基础上衍生下来的.为了避免重复造轮子,这里会结合网上demo,和自己理解进行总结 定义:备忘录(Memento)模式又称标记(Token)模式.G ...

  9. 设计模式-备忘录模式(Memento)-Java

    设计模式-备忘录模式(Memento)-Java 目录 文章目录 1.前言 2.示例案例-可悔棋的中国象棋 3.备忘录模式概述 3.1.备忘录模式定义 3.2.备忘录模式结构 3.3.备忘录模式结构图 ...

最新文章

  1. PostgreSQL 8.2.5 安装为 Windows 服务 (Service)
  2. Python 技术篇-httpClient库连接服务器发送请求解析响应实例演示,No module named ‘httplib‘问题解决方法
  3. matlab中tenmat,tensor_toolbox_2.5 2014最新的张量的工具包, 中包含了各种 函数。 matlab 238万源代码下载- www.pudn.com...
  4. python构建bp神经网络_鸢尾花分类(一个隐藏层)__1.数据集
  5. 面试官问你final、finally、finalize的区别
  6. 在VC++ 6.0下利用共享内存、消息实现内部进程通讯
  7. go语言阶段综合练习--家庭收支软件的示例--过程版本
  8. Python和Matlab系统比较
  9. Android如何实现汉字手写输入法(带中文自动识别提示)
  10. html拾色器没效果,用html和js写一个拾色器
  11. AS+图灵机器人官网+HTTP POST(json)+JsonReader实现安卓课设《智能聊天机器人》填坑记录
  12. 服务器无线网卡禁止怎么办,台式机无线网卡被禁用了如何解决
  13. 光条中心线提取-Steger算法(基于Hessian矩阵)类似于ArcScan提取道路中心线
  14. 袋鼠云研发手记 | 袋鼠云EasyManager的TypeScript重构纪要...
  15. html下拉框动态增加成员,JavaScript实现左右下拉框动态增删示例
  16. RSA实现对文件的加密解密
  17. K8s 所有常用端口
  18. android 自动唤醒解锁,Android-唤醒并解锁Devi
  19. 数据血缘Atlas Rest-API使用
  20. Linux为什么无法进入文件,Linux系统运维之CentOS下提示“无法打开并写入文件”问题解决...

热门文章

  1. VMware Identity Manager 与CAS, Keycloak的集成
  2. 使用访问控制列表控制用户登录
  3. ping C类地址是否在线
  4. HP Network Team #1: PROBLEM
  5. 网站down掉后,自动发信的shell
  6. GNU源码安装借用YUM排除故障
  7. 【Pycharm】专业版连接xshell 远程服务器
  8. SpringCloud教程- 服务链路追踪(Spring Cloud Sleuth)(SpringCloud版本Greenwich.SR4)
  9. 【GVA】gorm多对多many2many删除数据的同时级联删除关联中间表中的关联数据
  10. linux fedora自定义终端terminal的快捷键