您的位置:首页 > 其它

生活中的状态模式

2015-08-28 11:03 549 查看


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


什么是状态?

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

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




以水为例说状态模式

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


水之三态

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


水与状态之间的类图关系

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

Water.h:
#ifndef __WATER_H__

#define __WATER_H__

//===============================================================

class State;

//===============================================================

class Water

{

public:

Water();

Water(State* pState, const string& strName);

~Water();

public:

//改变状态

bool ChangeState(State* pState);

//设置温度

void SetTemperature(int nTemperature);

//获取温度

int GetTemperature();

//升温,nStep升高的幅度

void RiseTemperature(int nStep);

//降温,nStep降低的幅度

void ReduceTemperature(int nStep);

//获取名称

string GetName();

//水的作用(功效)

void DoWork();

private:

int			m_nTemperature;			//水温

string		m_strName;				//名称

State*		m_pState;				//状态

};

#endif	//__WATER_H__


State.h:
#ifndef __STATE_H__

#define __STATE_H__

//===============================================================

class Water;

//===============================================================

class State

{

public:

virtual ~State() { }

//某一状态下表现的行为,用途

virtual void DoWork(Water* pWater) = 0;

virtual string GetStateName();

protected:

State(const string& strName) : m_strStateName(strName){}

string m_strStateName;

};

class SolidState : public State

{

public:

static SolidState* GetInstance();

virtual void DoWork(Water* pWater);

private:

SolidState(const string& strName) : State(strName) { }

static SolidState* s_pSolidState;

class CGarbo{

public:

~CGarbo()

{

if (SolidState::s_pSolidState != NULL)

{

delete SolidState::s_pSolidState;

}

}

};

static CGarbo s_Carbo;

};

class LiquidState : public State

{

public:

static LiquidState* GetInstance();

virtual void DoWork(Water* pWater);

private:

LiquidState(const string& strName) : State(strName) { }

static LiquidState* s_pLiquidState;

class CGarbo{

public:

~CGarbo()

{

if (LiquidState::s_pLiquidState != NULL)

{

delete LiquidState::s_pLiquidState;

}

}

};

static CGarbo s_Carbo;

};

class GaseousState : public State

{

public:

static GaseousState* GetInstance();

virtual void DoWork(Water* pWater);

private:

GaseousState(const string& strName) : State(strName){ }

static GaseousState* s_pGaseousState;

class CGarbo{

public:

~CGarbo()

{

if (GaseousState::s_pGaseousState != NULL)

{

delete GaseousState::s_pGaseousState;

}

}

};

static CGarbo s_Carbo;

};

#endif	//__STATE_H__


Water.cpp:
#include "stdafx.h"

#include "Water.h"

#include "State.h"

Water::Water() : m_pState(NULL), m_strName("水(H2O)")

{

SetTemperature(25);

}

Water::Water( State* pState, const string& strName) : m_nTemperature(0), m_pState(pState), m_strName(strName)

{

if (m_pState->GetStateName().compare("固态") == 0)

{

m_nTemperature = -25;

} else if (m_pState->GetStateName().compare("液态") == 0)

{

m_nTemperature = 25;

} else if (m_pState->GetStateName().compare("气态") == 0)

{

m_nTemperature = 125;

}

}

Water::~Water()

{

}

bool Water::ChangeState( State* pState )

{

if (!pState)

{

return false;

}

if (!m_pState)

{

cout << "初始化为" << pState->GetStateName() << endl;

} else

{

cout << "由" << m_pState->GetStateName() << "变为" << pState->GetStateName() << endl;

}

m_pState = pState;

return true;

}

void Water::SetTemperature( int nTemperature )

{

m_nTemperature = nTemperature;

if (m_nTemperature <= 0)

{

ChangeState(SolidState::GetInstance());

} else if (m_nTemperature > 0 && m_nTemperature <= 100)

{

ChangeState(LiquidState::GetInstance());

} else

{

ChangeState(GaseousState::GetInstance());

}

}

int Water::GetTemperature()

{

return m_nTemperature;

}

void Water::RiseTemperature( int nStep )

{

SetTemperature(m_nTemperature + nStep);

}

void Water::ReduceTemperature( int nStep )

{

SetTemperature(m_nTemperature - nStep);

}

std::string Water::GetName()

{

return m_strName;

}

void Water::DoWork()

{

if (m_pState)

{

m_pState->DoWork(this);

}

}


State.cpp:
#include "stdafx.h"

#include "State.h"

#include "Water.h"

string State::GetStateName()

{

return m_strStateName;

}

//===============================================================

SolidState* SolidState::s_pSolidState = NULL;

LiquidState* LiquidState::s_pLiquidState = NULL;

GaseousState* GaseousState::s_pGaseousState = NULL;

//===============================================================

SolidState* SolidState::GetInstance()

{

if (!s_pSolidState)

{

s_pSolidState = new SolidState("固态");

}

return s_pSolidState;

}

void SolidState::DoWork( Water* pWater )

{

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

<< "我坚如钢铁,仿如一冷血动物,请用我砸人,嘿嘿……" << endl;

}

LiquidState* LiquidState::GetInstance()

{

if (!s_pLiquidState)

{

s_pLiquidState = new LiquidState("液态");

}

return s_pLiquidState;

}

void LiquidState::DoWork( Water* pWater )

{

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

<< "我可滋润万物,饮用我可让你活力倍增……" << endl;

}

GaseousState* GaseousState::GetInstance()

{

if (!s_pGaseousState)

{

s_pGaseousState = new GaseousState("气态");

}

return s_pGaseousState;

}

void GaseousState::DoWork( Water* pWater )

{

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

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

}


测试代码:
void TestStateDesign()

{

Water water;

water.DoWork();

water.SetTemperature(-4);

water.DoWork();

water.RiseTemperature(8);

water.DoWork();

water.RiseTemperature(110);

water.DoWork();

water.ReduceTemperature(130);

water.DoWork();

}


结果如下:

初始化为液态

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

由液态变为固态

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

由固态变为液态

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

由液态变为气态

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

我将达到无我的境界……

由气态变为固态

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

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


水与状态之间的类图关系

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


状态模式总结

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


状态模式结构图

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

来自:http://ink.csdn.net/articles/show/55bd90a716baab4d3fc33fdd
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: