生活中的状态模式——水之三态

news/2024/7/4 0:53:12 标签: class
class="baidu_pl">
class="article_content clearfix">
class="markdown_views prism-atom-one-light">

生活中的状态模式——水之三态

什么是状态?

状态即事物所处的某一种形态。状态模式是说一个对象在其内部状态发生改变时,其表现的行为和外在属性不一样,这个对象看上去就像是改变了它的类型一样。因此,状态模式又称为对象的行为模式。

如我们生活中经常见到的水,就有三种不同状态冰、水、水蒸汽,三种状态所表现的外在性质完全不一样:1.冰,质坚硬,无流动性,表面光滑;2.水,具有流动性;3.水蒸汽,肉眼看不见,却存在于空气中,质轻。这三种状态特性是不相差巨大?简直就不像是同一种物质的,但事实却是不管它是在什么状态,其特里组成都是一样的,都是水分子(H2O)。

以水为例说状态模式

你还记得初中物理学书上的这副图吗?水有三种状态:固、液、气,三种状态表现出不同的特性和行为,它们之间的转换也伴随着一着热力学的现象。现在要用程序来模拟水的三种状态和相互转换,要如何实现呢?

水之三态

我们从对象的角度来考虑会有哪个类,首先不管它是什么状态始终是水(H2O),所以会有一个Water类;而它又有三种状态,我们可以定义三个状态类:SolidState、LiquidState、GaseousState;从SolidState、LiquidState、GaseousState这三个单词中我们会发现都有一个State后缀,于是我们会想它们之间是否有一些共性,能否提取出一个更抽象的类,这个类就是状态类(State)。这些类之间的关系大致如下:

水与状态之间的类图关系

Ok,我们已经知道了大概的关系,那就开始Coding实现吧,在实现的过程中不断完善……

class="prettyprint">class="language-Java hljs cs">Water.h:

class="hljs-preprocessor">#ifndef __WATER_H__

class="hljs-preprocessor">#class="hljs-keyword">define __WATER_H__

class="hljs-comment">//===============================================================

class State;

class="hljs-comment">//===============================================================

class Water

{

class="hljs-keyword">public:

    class="hljs-title">Water();

    Water(State* pState, class="hljs-keyword">const class="hljs-keyword">string& strName);

    ~Water();

class="hljs-keyword">public:

    //改变状态

    class="hljs-keyword">bool class="hljs-title">ChangeState(State* pState);

    class="hljs-comment">//设置温度

    class="hljs-keyword">void SetTemperature(class="hljs-keyword">int nTemperature);

    class="hljs-comment">//获取温度

    class="hljs-keyword">int GetTemperature();

    class="hljs-comment">//升温,nStep升高的幅度

    class="hljs-keyword">void RiseTemperature(class="hljs-keyword">int nStep);

    class="hljs-comment">//降温,nStep降低的幅度

    class="hljs-keyword">void ReduceTemperature(class="hljs-keyword">int nStep);

    class="hljs-comment">//获取名称

    class="hljs-keyword">string GetName();

    class="hljs-comment">//水的作用(功效)

    class="hljs-keyword">void DoWork();

class="hljs-keyword">private:

    class="hljs-keyword">int         m_nTemperature;         class="hljs-comment">//水温

    class="hljs-keyword">string      m_strName;              class="hljs-comment">//名称

    State*      m_pState;               class="hljs-comment">//状态

};

class="hljs-preprocessor">#class="hljs-keyword">endif  //__WATER_H__

State.h:

class="hljs-preprocessor">#ifndef __STATE_H__

class="hljs-preprocessor">#class="hljs-keyword">define __STATE_H__

class="hljs-comment">//===============================================================

class Water;

class="hljs-comment">//===============================================================

class State

{

class="hljs-keyword">public:

    class="hljs-keyword">virtual ~class="hljs-title">State() { }

    class="hljs-comment">//某一状态下表现的行为,用途

    class="hljs-keyword">virtual class="hljs-keyword">void DoWork(Water* pWater) = class="hljs-number">0;

    class="hljs-keyword">virtual class="hljs-keyword">string GetStateName();

class="hljs-keyword">protected:

    class="hljs-title">State(class="hljs-keyword">const class="hljs-keyword">string& strName) : class="hljs-title">m_strStateName(strName){}

    class="hljs-keyword">string m_strStateName;

};

class SolidState : class="hljs-keyword">public State

{

class="hljs-keyword">public:

    class="hljs-keyword">static SolidState* class="hljs-title">GetInstance();

    class="hljs-keyword">virtual class="hljs-keyword">void DoWork(Water* pWater);

class="hljs-keyword">private:

    class="hljs-title">SolidState(class="hljs-keyword">const class="hljs-keyword">string& strName) : class="hljs-title">State(strName) { }

    class="hljs-keyword">static SolidState* s_pSolidState;

    class CGarbo{

    class="hljs-keyword">public:

        ~class="hljs-title">CGarbo()

        {

            class="hljs-keyword">if (SolidState::s_pSolidState != NULL)

            {

                delete SolidState::s_pSolidState;

            }

        }

    };

    class="hljs-keyword">static CGarbo s_Carbo;

};

class LiquidState : class="hljs-keyword">public State

{

class="hljs-keyword">public:

    class="hljs-keyword">static LiquidState* class="hljs-title">GetInstance();

    class="hljs-keyword">virtual class="hljs-keyword">void DoWork(Water* pWater);

class="hljs-keyword">private:

    class="hljs-title">LiquidState(class="hljs-keyword">const class="hljs-keyword">string& strName) : class="hljs-title">State(strName) { }

    class="hljs-keyword">static LiquidState* s_pLiquidState;

    class CGarbo{

    class="hljs-keyword">public:

        ~class="hljs-title">CGarbo()

        {

            class="hljs-keyword">if (LiquidState::s_pLiquidState != NULL)

            {

                delete LiquidState::s_pLiquidState;

            }

        }

    };

    class="hljs-keyword">static CGarbo s_Carbo;

};

class GaseousState : class="hljs-keyword">public State

{

class="hljs-keyword">public:

    class="hljs-keyword">static GaseousState* class="hljs-title">GetInstance();

    class="hljs-keyword">virtual class="hljs-keyword">void DoWork(Water* pWater);

class="hljs-keyword">private:

    class="hljs-title">GaseousState(class="hljs-keyword">const class="hljs-keyword">string& strName) : class="hljs-title">State(strName){ }

    class="hljs-keyword">static GaseousState* s_pGaseousState;

    class CGarbo{

    class="hljs-keyword">public:

        ~class="hljs-title">CGarbo()

        {

            class="hljs-keyword">if (GaseousState::s_pGaseousState != NULL)

            {

                delete GaseousState::s_pGaseousState;

            }

        }

    };

    class="hljs-keyword">static CGarbo s_Carbo;

};

class="hljs-preprocessor">#class="hljs-keyword">endif  //__STATE_H__

Water.cpp:

class="hljs-preprocessor">#include "stdafx.h"

class="hljs-preprocessor">#include "Water.h"

class="hljs-preprocessor">#include "State.h"

Water::Water() : m_pState(NULL), m_strName(class="hljs-string">"水(H2O)")

{

    SetTemperature(class="hljs-number">25);

}

Water::Water( State* pState, class="hljs-keyword">const class="hljs-keyword">string& strName) : m_nTemperature(class="hljs-number">0), m_pState(pState), m_strName(strName)

{

    class="hljs-keyword">if (m_pState->GetStateName().compare(class="hljs-string">"固态") == class="hljs-number">0)

    {

        m_nTemperature = -class="hljs-number">25;

    } class="hljs-keyword">else class="hljs-keyword">if (m_pState->GetStateName().compare(class="hljs-string">"液态") == class="hljs-number">0)

    {

        m_nTemperature = class="hljs-number">25;

    } class="hljs-keyword">else class="hljs-keyword">if (m_pState->GetStateName().compare(class="hljs-string">"气态") == class="hljs-number">0)

    {

        m_nTemperature = class="hljs-number">125;

    }

}

Water::~Water()

{

}

class="hljs-keyword">bool Water::ChangeState( State* pState )

{

    class="hljs-keyword">if (!pState)

    {

        class="hljs-keyword">return class="hljs-keyword">false;

    }

    class="hljs-keyword">if (!m_pState)

    {

        cout << class="hljs-string">"初始化为" << pState->GetStateName() << endl;

    } class="hljs-keyword">else

    {

        cout << class="hljs-string">"由" << m_pState->GetStateName() << class="hljs-string">"变为" << pState->GetStateName() << endl;

    }

    m_pState = pState;

    class="hljs-keyword">return class="hljs-keyword">true;

}

class="hljs-keyword">void Water::SetTemperature( class="hljs-keyword">int nTemperature )

{

    m_nTemperature = nTemperature;

    class="hljs-keyword">if (m_nTemperature <= class="hljs-number">0)

    {

        ChangeState(SolidState::GetInstance());

    } class="hljs-keyword">else class="hljs-keyword">if (m_nTemperature > class="hljs-number">0 && m_nTemperature <= class="hljs-number">100)

    {

        ChangeState(LiquidState::GetInstance());

    } class="hljs-keyword">else

    {

        ChangeState(GaseousState::GetInstance());

    }

}

class="hljs-keyword">int Water::GetTemperature()

{

    class="hljs-keyword">return m_nTemperature;

}

class="hljs-keyword">void Water::RiseTemperature( class="hljs-keyword">int nStep )

{

    SetTemperature(m_nTemperature + nStep);

}

class="hljs-keyword">void Water::ReduceTemperature( class="hljs-keyword">int nStep )

{

    SetTemperature(m_nTemperature - nStep);

}

std::class="hljs-keyword">string Water::GetName()

{

    class="hljs-keyword">return m_strName;

}

class="hljs-keyword">void Water::DoWork()

{

    class="hljs-keyword">if (m_pState)

    {

        m_pState->DoWork(class="hljs-keyword">this);

    }

}

State.cpp:

class="hljs-preprocessor">#include "stdafx.h"

class="hljs-preprocessor">#include "State.h"

class="hljs-preprocessor">#include "Water.h"

class="hljs-keyword">string State::GetStateName()

{

    class="hljs-keyword">return m_strStateName;

}

class="hljs-comment">//===============================================================

SolidState* SolidState::s_pSolidState = NULL;

LiquidState* LiquidState::s_pLiquidState = NULL;

GaseousState* GaseousState::s_pGaseousState = NULL;

class="hljs-comment">//===============================================================

SolidState* SolidState::GetInstance()

{

    class="hljs-keyword">if (!s_pSolidState)

    {

        s_pSolidState = class="hljs-keyword">new SolidState(class="hljs-string">"固态");

    }

    class="hljs-keyword">return s_pSolidState;

}

class="hljs-keyword">void SolidState::DoWork( Water* pWater )

{

    cout << class="hljs-string">"我性格高冷,当前体温" << pWater->GetTemperature() << class="hljs-string">"摄氏度,"

    << class="hljs-string">"我坚如钢铁,仿如一冷血动物,请用我砸人,嘿嘿……" << endl;

}

LiquidState* LiquidState::GetInstance()

{

    class="hljs-keyword">if (!s_pLiquidState)

    {

        s_pLiquidState = class="hljs-keyword">new LiquidState(class="hljs-string">"液态");

    }

    class="hljs-keyword">return s_pLiquidState;

}

class="hljs-keyword">void LiquidState::DoWork( Water* pWater )

{

    cout << class="hljs-string">"我性格温和,当前体温" << pWater->GetTemperature() << class="hljs-string">"摄氏度,"

    << class="hljs-string">"我可滋润万物,饮用我可让你活力倍增……" << endl;

}

GaseousState* GaseousState::GetInstance()

{

    class="hljs-keyword">if (!s_pGaseousState)

    {

        s_pGaseousState = class="hljs-keyword">new GaseousState(class="hljs-string">"气态");

    }

    class="hljs-keyword">return s_pGaseousState;

}

class="hljs-keyword">void GaseousState::DoWork( Water* pWater )

{

    cout << class="hljs-string">"我性格热烈,当前体温" << pWater->GetTemperature() << class="hljs-string">"摄氏度,"

    << class="hljs-string">"飞向天空是我毕生的梦想,在这你将看不到我的存在,我将达到无我的境界……" << endl;

}




测试代码:

class="hljs-keyword">void TestStateDesign()

{

    Water water;

    water.DoWork();

    water.SetTemperature(-class="hljs-number">4);

    water.DoWork();

    water.RiseTemperature(class="hljs-number">8);

    water.DoWork();

    water.RiseTemperature(class="hljs-number">110);

    water.DoWork();

    water.ReduceTemperature(class="hljs-number">130);

    water.DoWork();

}

结果如下:

初始化为液态

我性格温和,当前体温25摄氏度,我可滋润万物,饮用我可让你活力倍增……

由液态变为固态

我性格高冷,当前体温-4摄氏度,我坚如钢铁,仿如一冷血动物,请用我砸人,嘿嘿……

由固态变为液态

我性格温和,当前体温4摄氏度,我可滋润万物,饮用我可让你活力倍增……

由液态变为气态

我性格热烈,当前体温114摄氏度,飞向天空是我毕生的梦想,在这你将看不到我的存在,

我将达到无我的境界……

由气态变为固态

我性格高冷,当前体温-16摄氏度,我坚如钢铁,仿如一冷血动物,请用我砸人,嘿嘿……

好了,上面的程序已经完美地帮我们完成了水的三种状态及其转变的模拟。我们再来整理一个上面的代码中的类图结构,如下图:

水与状态之间的类图关系

SolidState、LiquidState、GaseousState三个类用了单例的模式,因为状态只需要一个对象就可以了,这三个类中CGarbo是一个内部类,只为了释放静态对象,关于单例模式的用法,可以参考《生活中的单例——不是单身》。Water中的ChangeState可方便地进行三种状态之间的转换。

状态模式总结

通过上面一个生活中的例子,应该很容易能明白状态模式吧!其实也简单,其结构关系如下:

状态模式结构图

Behavior是不同一个对象在不同状态下的行为(如DoWork),ChangeState用于改变对象的状态,Request则是操作请求(如RiseTemperature和)。


http://www.niftyadmin.cn/n/1317959.html

相关文章

数据结构与算法实验1实现顺序表各种基本运算的算法

数据结构与算法实验1实现顺序表各种基本运算的算法 “顺序表功能展示” “1.初始化顺序表” “2.指定位置插入单个元素” “3.输出顺序表” “4.输出顺序表长度” “5.输出顺序表第a个元素” “7.指定位置删除单个元素” “0.释放顺序表” 代码部分 #include<iostream> …

生活中的观察者模式——一壶水的故事

生活中的观察者模式——一壶水的故事 观察者模式&#xff0c;顾名思意就是观察与被观察的关系&#xff0c;比如你在烧开水得时时看着它开没开&#xff0c;你就是观察者&#xff0c;开水就是被观察者&#xff1b;再比如说你在带小孩&#xff0c;你关注她是不是饿了&#xff0c;…

实现单链表各种基本运算的算法

#include <iostream> #include <stdio.h> #include <stdlib.h> using namespace std;//单链表节点定义 typedef struct LNode {int data;struct LNode* next; }LNode, * LinkList; LinkList L;//1.前插法初始化单链表 void CreatList_head(LinkList& L, …

渗透攻防Web篇-SQL注入攻击初级 1

Preface 不管用什么语言编写的Web应用&#xff0c;它们都用一个共同点&#xff0c;具有交互性并且多数是数据库驱动。在网络中&#xff0c;数据库驱动的Web应用随处可见&#xff0c;由此而存在的SQL注入是影响企业运营且最具破坏性的漏洞之一&#xff0c;这里我想问&#xff0…

C++简单游戏 猜数字

#include<iostream> #include<ctime> using namespace std; int main() {int a;srand((unsigned int)time(NULL));int num rand() % 10000 1;cout << "请玩家输入猜测数字" << endl;while (1){cin >> a;if (a > num){cout <&l…

Python之道-爬虫1

“形而上者为之道&#xff0c;形而下者为之器“ 学编程语言&#xff0c;应学习其核心思想&#xff0c;掌握其精髓&#xff01;应懂得透过现象抓到本质的东西&#xff1b; 建立此系列博文&#xff0c;理清自己的思路&#xff0c;Python大道渊源流长&#xff0c;且行且珍惜。 …

C++前期知识实现简单的通讯录系统

#include<iostream> using namespace std; void showMenu(); void end0(); #define max 1000struct News {string name;string sex;int age;int phone;string site; }; struct books {struct News news[max];int size; };void showMenu() {cout << " 1.添加联…

Web安全工程师(学习规划)

WEB安全工程师 简介: web安全工程师是信息安全领域的一个职位&#xff0c;它负责对公司网站、业务系统进行安全评估测试&#xff1b;对公司各类系统进行安全加固&#xff1b;对公司安全事件进行响应&#xff0c;清理后门&#xff0c;根据日志分析攻击途径&#xff1b;安全技术…