欢迎访问 生活随笔!

凯发k8官方网

当前位置: 凯发k8官方网 > 编程语言 > asp.net >内容正文

asp.net

设计模式的理解:状态模式(state) 和备忘录模式(memento) -凯发k8官方网

发布时间:2024/10/14 asp.net 29 豆豆
凯发k8官方网 收集整理的这篇文章主要介绍了 设计模式的理解:状态模式(state) 和备忘录模式(memento) 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

  状态模式,允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。它的实现方式和策略模式相似,目的都是对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:"<当操作方法发生需求变更时,方法一代码这样写影响范围就会覆盖整个流程,代码不易维护,不易扩展。如果增加状态,那么枚举要新增,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) 获取原对象重要的属性,并对这些属性进行隐藏

 

总结

以上是凯发k8官方网为你收集整理的设计模式的理解:状态模式(state) 和备忘录模式(memento)的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得凯发k8官方网网站内容还不错,欢迎将凯发k8官方网推荐给好友。

网站地图