Behavior.State(行为型模式—状态模式)

状态模式(State Pattern)的定义

(1)定义:允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

  ①状态和行为,它们的关系可以描述为状态决定行为

  ②因状态是在运行期被改变,行为也会在运行期根据状态的改变而改变。看起来,同一个对象,在不同的运行时刻,行为是不一样的,就像是类被修改了一样

(2)状态模式的结构和说明

 

  ①Context:环境,也称上下文,通常用来定义客户感兴趣的接口,同时维护一个来具体处理当前状态的实例对象

  ②State:状态接口,用来封装与上下文的一个特定状态所对应的行为。

  ③ConcreteState:具体实现状态处理的类,每个类实现一个跟上下文相关的状态的具体处理。

思考状态模式

(1)状态模式的本质:根据状态来分离和选择行为

(2)状态和行为

  ①状态模式的功能就是把状态和状态对应的行为分离出来,每个状态所对应的功能处理封装在一个独立的类里。通过维护状态的变化,来调用不同状态对应的不同功能。

  ②为了操作不同的状态类,定义一个状态接口来约束它们,这样外部就可以面向这个统一的状态接口编程,而无须关心具体的状态类实现了。

  ③状态和行为是相关联的,它们的关系可以描述为状态决定行为。因状态是在运行期被改变,行为也会在运行期根据状态的改变而改变,看起来,同一个对象,在不同的运行时刻,行为是不一样的,就像是类被修改了一样。

(3)行为的平行性

  ①注意是平行性,而不是平等性。所谓的平行性指的是各个状态的行为所处的层次是一样的,相互独立的、没有关联的,是根据不同的状态来决定到底走平行线的哪一条。因为行为是不同的,当然对应的实现也是不同的,相互之间是不可替换的

 

  ②平等性:强调用的可替换性,大家是同一行为的不同描述或实现,因此在同一个行为发生的时候,可以根据条件挑选任意一个实现来进行相应的处理。

 

  ③状态模式的结构和策略模式的结构完全一样。但是它们的目的、实现、本质却完全不同。还有行为之间的特性也是状态模式和策略模式的一个很重要的区别,状态模式的行为是平行性,不可相互替换的;而策略模式的行为是平等的,是可以相互替换的

(4)Context和state

  ①在状态模式中,上下文持有state对象,但上下文本身并不处理跟状态相关的行为,而是把处理状态的功能委托给了状态对应的状态处理类来处理

  ②在具体的状态处理类经常需要获取上下文自身的数据,甚至在必要的时候回调上下文中的方法。因此,通常将上下文自身当作一个参数传递给具体的状态处理类

  ③客户端一般只和上下文交互。客户端通常不负责运行期间状态的维护,也不负责决定后续到底使用哪一个具体的状态处理对象,这点与策略模式是不同的

(5)不完美的OCP体验(开闭原则)

  ①修改功能:由于每个状态对应的处理己经封装到对应的状态类中了,要修改己有的某个状态的功能,直接进行修改那个类就可以了,对其他程序没有影响。

  ②添加新的实现类:得修改Context中request方法这不完全遵循OCP原则。这要说明一下,设计原则是大家在设计和开发中尽量去遵守的,但不是一定要遵守,尤其是完全遵守。因为实际开发中,完全遵守那些原则几乎是不可能完成的任务。

(6)创建和销毁状态对象

  ①如果要进入的状态在运行时是不可知的,而且上下文是比较稳定的,不会经常改变状态,而且使用也不频繁的,可以在需要状态对象的时候创建,使用完销毁它们

  ②如果状态改变很频繁,也就是需要频繁的创建状态对象,而且状态对象还存储着大量的数量信息,这种情况可以提前创建它们并且始终不销毁

  ③如果无法确定状态改变是否频繁,而且有些状态对象的数据量大,有些比较小,一切都是未知的,可以采用延迟加载和缓存结合的方式,就是当第一次需要使用状态对象时创建,使用完后并不销毁对象,而是把这个对象缓存起来,等待一下次使用,而且在合适的时候,由缓存框架销毁状态对象。在实际工程开发过程中,这个方案是首选,因为它兼顾了前两种方案的优点,又避免了它们的缺点。

【编程实验】你公司力排万难终于获得某个酒店的系统开发项目,并且最终落到了你的头上。下图是他们系统的主要工作(够简单)。 当你第一眼看到这个系统的时候你就看出来了这是一个状态图,每个框框都代表了房间的状态,箭头表示房间状态的转换。分析如下:房间有三个状态:空闲、已预订、已入住,状态与状态之间可以根据客户的动作来进行转换。定义每个状态的值。


图片1

aaaa

//声明文件

#include<iostream>
#include<iomanip>
using namespace std;



class CAbsState{
public:
	virtual void BookRoom() = 0;//预订房间 
	virtual void UnsubscribeRoom() = 0;//退订房间 
	virtual void CheckInRoom() = 0;//入住
	virtual void CheckOutRoom() = 0;//退房
};

//房间  
class CRoom{
private:
	CAbsState* pFreeState;//空闲状态
	CAbsState* pCheckInState;//入住状态
	CAbsState* pBookedState;//预订状态
	CAbsState* pCurrState;//当前状态
public:
	CRoom();
	~CRoom();
	void BookRoom();
	void UnsubscribeRoom();
	void CheckInRoom();
	void CheckOutRoom();
	void RoomState();
public:
	void SetFreeState(CAbsState* freestate);
	CAbsState* GetFreeState();
	void SetCheckInState(CAbsState* checkinstate);
	CAbsState* GetCheckInState();
	void SetBookedState(CAbsState* bookedstate);
	CAbsState* GetBookedState();
	void SetCurrState(CAbsState* currstate);
	CAbsState* GetCurrState();
};
//空闲状态只能预订和入住
class CFreeState : public CAbsState{
private:
	CRoom* pRoom;
public:
	CFreeState(CRoom* room);
	void BookRoom();
	void CheckInRoom();
	void UnsubscribeRoom();
	void CheckOutRoom();
};
//预定的房间可以退订和入住
class CBookedState : public CAbsState{
private:
	CRoom* pRoom;
public:
	CBookedState(CRoom* room);
	void BookRoom();
	void CheckInRoom();
	void CheckOutRoom();
	void UnsubscribeRoom();
};

// 入住可以退房 
class CCheckInState : public CAbsState{
private:
	CRoom* pRoom;
public:
	CCheckInState(CRoom* room);
	void BookRoom();
	void CheckInRoom();
	void CheckOutRoom();
	void UnsubscribeRoom();
};

//实现文件

void CRoom::BookRoom(){ pCurrState->BookRoom();}//预订房间
void CRoom::UnsubscribeRoom(){pCurrState->UnsubscribeRoom();}//退订房间
void CRoom::CheckInRoom(){pCurrState->CheckInRoom();}//入住
void CRoom::CheckOutRoom(){pCurrState->CheckOutRoom();}//退房
void CRoom::RoomState(){cout << "该房间的状态是:" << typeid(*pCurrState).name() << endl;}
void CRoom::SetFreeState(CAbsState* freestate){pFreeState = freestate;}
CAbsState* CRoom::GetFreeState(){return pFreeState;}
void CRoom::SetCheckInState(CAbsState* checkinstate){pCheckInState = checkinstate;}
CAbsState* CRoom::GetCheckInState(){return pCheckInState;}
void CRoom::SetBookedState(CAbsState* bookedstate){pBookedState = bookedstate;}
CAbsState* CRoom::GetBookedState(){return pBookedState;}
void CRoom::SetCurrState(CAbsState* currstate){pCurrState = currstate;}
CAbsState* CRoom::GetCurrState(){return pCurrState;}


CFreeState::CFreeState(CRoom* room){pRoom = room;}
void CFreeState::BookRoom(){
	cout << "您已经成功预订了..." << endl;
	pRoom->SetCurrState(pRoom->GetBookedState());//状态变成已经预订
}
void CFreeState::CheckInRoom(){
	cout << "您已经成功入住了..." << endl;
	pRoom->SetCurrState(pRoom->GetCheckInState());//状态变成已经入住
}
void CFreeState::UnsubscribeRoom(){/*不需要做操作*/}
void CFreeState::CheckOutRoom(){/*不需要做操作*/}

//预定的房间可以退订和入住

CBookedState::CBookedState(CRoom* room){pRoom = room;}
void CBookedState::BookRoom(){cout << "该房间已近给预定了..." << endl;}
void CBookedState::CheckInRoom(){
	cout << "入住成功" << endl;
	pRoom->SetCurrState(pRoom->GetCheckInState());
}
void CBookedState::CheckOutRoom(){/*不需要做操作*/}
void CBookedState::UnsubscribeRoom(){
	cout << "退订成功,欢迎下次光临" << endl;
	pRoom->SetCurrState(pRoom->GetFreeState());//变成空闲状态
}

// 入住可以退房 
CCheckInState::CCheckInState(CRoom* room){pRoom = room;}
void CCheckInState::BookRoom(){
	cout << "该房间已经入住了..." << endl;
}
void CCheckInState::CheckInRoom(){
	cout << "该房间已经入住了..." << endl;
}
void CCheckInState::CheckOutRoom(){
	cout << "退房成功..." << endl;
	pRoom->SetCurrState(pRoom->GetFreeState());//状态变成空闲
}
void CCheckInState::UnsubscribeRoom(){/*不需要做操作*/}



CRoom::CRoom(){//房间的三个状态 
	pFreeState = new CFreeState(this);
	pCheckInState = new CCheckInState(this);
	pBookedState = new CBookedState(this);
	pCurrState = pFreeState;////初始状态为空闲 
}
CRoom::~CRoom(){
	delete pFreeState;
	delete pCheckInState;
	delete pBookedState;
}

//测试客户端

void main()
{
	CRoom* pRoom1 = new CRoom();
	CRoom* pRoom2 = new CRoom();
	//第一间房 : 预订--->入住---预订
	cout << "第一间房***************************" << endl;
	pRoom1->BookRoom();
	pRoom1->CheckInRoom();
	pRoom1->BookRoom();//Failed
	pRoom1->RoomState();
	cout << "第二间房***************************" << endl;
	pRoom2->CheckInRoom();
	pRoom2->BookRoom();//Failed
	pRoom2->CheckOutRoom();
	pRoom2->BookRoom();
	pRoom2->RoomState();
	delete pRoom1;
	delete pRoom2;
}

猜你喜欢

转载自blog.csdn.net/knightonhourse/article/details/80017198