面向对象程序设计第七次实验课——状态模式

来源:互联网 发布:ae渲染快捷键 mac 编辑:程序博客网 时间:2024/06/04 19:33

题目要求是自己开脑洞想一个状态模式的例子,实现之。
例子详见后文。
状态模式简介:
http://www.cnblogs.com/wangjq/archive/2012/07/16/2593485.html

State.h

#pragma once#include "Person.h"class Person;class State{    public:        State() = default;        ~State() = default;        virtual void study(Person *per) = 0;        virtual void play(Person *per) = 0;        virtual void eat(Person *per) = 0;        virtual void exam(Person *per) = 0;        void sleep(Person *per);};

State.cpp

#include "State.h"#include "Person.h"#include <iostream>using namespace std;void State::sleep(Person *per){    cout << "Sound Sleep ~" << endl;    cout << "a new day is coming ~" << endl;    per -> setstate(per -> getNewState());    return ;}

Exciting.h

#pragma once#include "State.h"class Exciting : public State{    public:        Exciting() = default;        ~Exciting() = default;        virtual void study(Person *per) override;        virtual void play(Person *per) override;        virtual void eat(Person *per) override;        virtual void exam(Person *per) override;};

Exciting.cpp

#include <iostream>#include "Exciting.h"#include "Person.h"#include "Happy.h"#include "Sad.h"#include "Soso.h"using namespace std;void Exciting::study(Person *per){    cout << "Excited! Study!" << endl;    cout << "Gain lots of knowledge! You're content with yourself~" << endl;    per -> setstate(new Happy);    cout << "Get into Happy Mode ~" << endl;    return ;}void Exciting::play(Person *per){    cout << "Excited! Play!" << endl;    cout << "You win a lot!" << endl;    cout << "Still Exciting!" << endl;}void Exciting::eat(Person *per){    cout << "Excited! Eat!" << endl;    cout << "You eat too much!" << endl;    per -> setstate(new Soso);    cout << "Get into Soso Mode" << endl;}void Exciting::exam(Person *per){    cout << "Excited! Exam!" << endl;    cout << "Too Excited to take an exam!" << endl;    cout << "You fail the exam!" << endl;    per ->setstate(new Sad);    cout << "Get into Sad Mode 555~" << endl;}

Happy.h

#pragma once#include "State.h"class Happy : public State{    public:        Happy() = default;        ~Happy() = default;        virtual void study(Person *per) override;        virtual void play(Person *per) override;        virtual void eat(Person *per) override;        virtual void exam(Person *per) override;};

Happy.cpp

#include "Happy.h"#include "Exciting.h"#include "Person.h"#include "Happy.h"#include "Sad.h"#include "Soso.h"#include <iostream>using namespace std;void Happy::study(Person *per){    cout << "Happy~ Study~" << endl;    cout << "Gain lots of knowledge~ You're proud of yourself!" << endl;    per -> setstate(new Exciting);    cout << "Get into Excited Mode !" << endl;    return ;}void Happy::play(Person *per){    cout << "Happy~ Play!" << endl;    cout << "You win a lot!" << endl;    per -> setstate(new Exciting);    cout << "Get into Excited Mode !" << endl;}void Happy::eat(Person *per){    cout << "Happy~ Eat~" << endl;    cout << "You eat well!" << endl;    cout << "Still Happy~" << endl;}void Happy::exam(Person *per){    cout << "Happy~ Exam..." << endl;    cout << "An hard exam... You do just soso" << endl;    per ->setstate(new Soso);    cout << "Get into SoSo Mode" << endl;}

Soso.h

#pragma once#include "State.h"class Soso : public State{    public:        Soso() = default;        ~Soso() = default;        virtual void study(Person *per) override;        virtual void play(Person *per) override;        virtual void eat(Person *per) override;        virtual void exam(Person *per) override;};

Soso.cpp

#include "Soso.h"#include "Person.h"#include "Sad.h"#include "Happy.h"#include "Exciting.h"#include <iostream>using namespace std;void Soso::study(Person *per){    cout << "Soso... Study..." << endl;    cout << "Hard to understand... You're tired..." << endl;    per -> setstate(new Sad);    cout << "Get into Sad Mode 555~" << endl;    return ;}void Soso::play(Person *per){    cout << "Soso... Play!" << endl;    cout << "You win some games~" << endl;    per -> setstate(new Happy);    cout << "Get into Happy Mode ~" << endl;}void Soso::eat(Person *per){    cout << "Soso... Eat~" << endl;    cout << "You eat well~" << endl;    per -> setstate(new Happy);    cout << "Get into Happy Mode ~" << endl;}void Soso::exam(Person *per){    cout << "Soso... Exam..." << endl;    cout << "An hard exam... You do not well 555~" << endl;    per ->setstate(new Sad);    cout << "Get into Sad Mode 555~" << endl;}

Sad.h

#pragma once#include "State.h"class Sad: public State{    public:        Sad() = default;        ~Sad() = default;        virtual void study(Person *per) override;        virtual void play(Person *per) override;        virtual void eat(Person *per) override;        virtual void exam(Person *per) override;};

Sad.cpp

#include "Person.h"#include "Sad.h"#include "Soso.h"#include "Happy.h"#include "Exciting.h"#include <iostream>using namespace std;void Sad::study(Person *per){    cout << "Sad 555~ Study~" << endl;    cout << "You forget the reason why you're Sad~" << endl;    per -> setstate(new Happy);    cout << "Get into Happy Mode ~" << endl;    return ;}void Sad::play(Person *per){    cout << "Sad 555~ Play!" << endl;    cout << "You win some games~" << endl;    per -> setstate(new Happy);    cout << "Get into soso Mode ..." << endl;}void Sad::eat(Person *per){    cout << "Sad 555~ Eat~" << endl;    cout << "You eat well~" << endl;    per -> setstate(new Soso);    cout << "Get into soso Mode ~" << endl;}void Sad::exam(Person *per){    cout << "Sad 555~ Exam 555~" << endl;    cout << "An hard exam... You do bad 555~" << endl;    cout << "You're extremely Sad 55555~" << endl;}

Person.h

#pragma once#include "State.h"class State;class Person{    public:        Person(void);         Person(State *state);        ~Person() = default;        void study(void);        void play(void);        void eat(void);        void exam(void);        void sleep(void);        const State* getstate(void);        void setstate(State *state);        State* getNewState(void);    private:        State *m_state;};

Person.cpp

#include "Person.h"#include "Happy.h"#include "Exciting.h"#include "Soso.h"#include "Sad.h"#include <iostream>using namespace std;Person::Person(State *state) : m_state(state) {}const State* Person::getstate(void){    return m_state;}void Person::setstate(State *state){    m_state = state;}State* Person::getNewState(void) {    cout << "choose your new state:" << endl;    cout << "1. Happy" << endl;    cout << "2. Excited" << endl;    cout << "3. So So" << endl;    cout << "4. Sad" << endl;    int state, flag = 1;    while (flag) {        cin >> state;        switch (state) {            case 1:                return new Happy;                break;            case 2:                return new Exciting;                break;            case 3:                return new Soso;                break;            case 4:                return new Sad;                break;            default:                ;        }     }}void Person::eat(void) {    m_state -> eat(this);    return ;}void Person::exam(void){    m_state -> exam(this);    return;}void Person::study(void){    m_state -> study(this);    return ;}void Person::play(void){    m_state -> play(this);    return ;}void Person::sleep(void){    m_state -> sleep(this);}

main.cpp

#include <iostream>#include "Group.h"#include "Decorator.h"#include "Life.h"#include "Business.h"#include "Study.h"#include <vector>using namespace std;int main(int argc, char** argv) {    Person per("Jason", "12345");    vector<Person *> vper;    vper.push_back(&per);    Group *p1 = new Group(vper);    Group *p2 = new Life(*p1);    Group *p3 = new Study(*p2);    Group *p4 = new Business(*p3);    per.sendMessage("hello!", *p4);    cout << endl;    per.sendMessage("hi!", *p2);    cout << endl;    per.getMessageRecord(*p1);    cout << endl;    per.getMessageRecord(*p4);    cout << endl;    return 0;}

第七次实验报告

一、 场景描述
首先说一下自己对于状态模式的理解。一个对象可能会在不同的时间不同的地点不同的情况会有不同的状态,而对应于不同的状态,这个对象的部分行为会有所改变,这就是状态模式出现的原因。我认为状态模式是用于解决一个这样一个情形:对象会有较多的状态,同时又有相当一部分行为会因为状态的改变而改变。
状态模式的基本模型是这样的,有一个具体的类描述一种事务,充当用户接口,并持有一个State类的指针。State类是一个抽象类,是所有具体状态的父类,它拥有关联类基于状态的行为的实现,规定了所有子类应该定义的行为。每一个具体的状态类依据状态定义行为。

我的程序描述了这样一个场景。有一个人(Person),他有五种行为(study、eat、play、exam、sleep),有四种心情(状态:happy、excited、so-so、sad),在不同的心情下,这个人做同一件事情会有不同的结果,相应的会有状态的变化。当一天结束,一个人sleep后可以选择新的一天以什么状态开始。

Person类中拥有一个State类型的指针m_state,动态类型是State的子类之一,在执行行为的时候,调用m_state指向对象的行为,行为过后,Person中m_state的动态类型可能改变。

二、 多态
为什么要多态呢?注意,状态模式要求对于不同的状态,对象的行为会发生改变。显然,这个状态并不是编译时确定的,而是运行时才能确定的,这符合多态的定义。因此,多态可以解决这一问题,只要把不同的状态抽象成不同的类,并使用一个相同的祖先类管理这些类,就可以用多态的思想解决问题。

三、不使用多态
我们当然可以用面向过程和基于对象的思想解决这一问题。我想到了两种方法。
(1)使用分支
在类中加入成员变量flag,用来标记当前的状态,比如1表示happy,2表示excited等等,当一个行为是基于状态的时候,讨论flag的值,根据不同的值执行不同的操作。
这一方法的优点是当这个对象仅有极少的行为依赖状态时,使用这种方法逻辑简单,易于理解,组织结构也简单,状态改变方便,而且也易于维护。缺点是,一旦过多的行为依赖状态,就需要在每个行为中都加入判断,不易于维护,代码难看。
(2)同一对象不同状态抽象成不同的对象
举个例子,如果Person有happy和excited两种状态,可以定义HappyPerson和ExcitedPerson两个类,并定义不同的行为。
这样的优点是在行为较多时相对于(1),一个类的内部不再过于冗杂,逻辑更加清晰,在行为较多且都依赖状态、状态极少时适用。缺点是不易于改变状态,没有共同的基类不方便管理,而且一旦状态变多,就需定义很多的类,而且当对象的行为并不都依赖于状态时,不同类之前就会有对相同行为的重复定义。
(3)引入基础
在(2)的基础上做修改,定义抽象基类Person,将依赖状态的行为定义为纯虚函数,而不依赖状态的行为不定义为虚函数,希望子类直接继承。子类为HappyPerson、ExcitedPerson… 实现基类中的纯虚函数。
优点是,相对于(2)而言,更加灵活,对象本身和状态的耦合性减弱,但同样继承了(2)中的缺点,难于改变状态,而且对于更加复杂的类,状态和行为的耦合程度依然较高。
从前3点的补补递进,不难想到在更加复杂的情况下,使用多态是更好的方法,不过,对于简单问题,如果上述3种方法可以很好的解决问题,那么使用状态模式也不是必须的,使用状态模式也有产生较多的状态类这一缺点。具体用哪种方法还需要具体分析。
四、双向关联类
在上一次实验中,我也使用了双向关联类:Person和Group,其中Person和Group的成员中都含有存储对方指针的容器。
这次实验中的Person和State同样是双向关联的,Person中含有State的指针,而State中方法的参数是Person的指针。
解决这一问题的关键是:在使用任何类型和调用任何函数之前,它们的声明或者定义必须已经在调用之前存在。
由于双向关联,需要引入前向声明。经过前向声明之后的类型是不完全类型,对于不完全类型,实例化该类型的对象是非法的(不知道对象的大小,编译器无法分配空间),但是定义该类型的指针和引用是合法的(引用的底层实现就是指针,指针的大小就是一个字长,对指针的解释取决于编译器,在底层指针(或者地址)本身就是无类型)。因此,使用前向声明就可以解决这一问题,双向关联的类中不可能包含另一个关联类的对象类型。而对于函数调用的问题,只要拥有良好的分文件习惯,导入对方类的.h文件,就可以解决了。

阅读全文
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小月子全身流虚汗怎么办 生完孩子严重便秘怎么办啊 产后第5天恶露少怎么办 有恶露排不出来怎么办 刚生完小孩便秘怎么办 产后15天有鲜血怎么办 恶露未净同房了怎么办 药流2月恶露不尽怎么办 生完孩子小腹痛怎么办 月子里恶露有异味怎么办 恶露干净了有异味怎么办 顺产后恶露白色异味怎么办 产妇排出的恶露有异味怎么办 恶露有股腥臭味怎么办 生完孩子下面有异味怎么办 销售货物开票税率错了怎么办 8h床垫有橡胶味怎么办 买回来的鞋子臭怎么办 耐克保修卡没了怎么办 雅萌保修卡没了怎么办 苹果保修卡没了怎么办 新车迟迟不给合格证怎么办 手机系统剩余空间少怎么办 桌子被掉色的袋子印色怎么办 袋子掉色弄到柜子上怎么办 健身房老板跑路教练怎么办 健身房老板跑路了怎么办 淘宝断货了该怎么办 淘金猫网购频道账号换了怎么办 京东商城信用卡无法付款怎么办 京东第三方退货拒收怎么办 淘宝凑单收货地址不一样怎么办 淘宝凑单地址不一样怎么办 任性付还不了款怎么办 京东购物卷删了怎么办 荣耀手环3进水了怎么办 手机疏油层没了怎么办 快递到了处理中心不走了怎么办 京东取消了退款怎么办 我的订单删除了怎么办 近邻宝箱子误关怎么办