「设计模式笔记」状态模式

前言

本文的知识都出自于『Head First 设计模式』这本书中,
这里只是做一个概括,等后来忘记了拿来复习。
你可以也将本文作为复习参考,
不过要学的话,建议还是去看原书吧。
看这本书不一定非要会Java,我就是用C++实现的。

定义

状态模式(State Pattern)允许对象在内部状态改变时改变他的行为,
由于状态模式完全改变对象行为,对象看起来就像修改了它的类。

如果不用状态模式,对象将使用变量或者枚举变量来存储当前状态,
然后执行行为时,就要用一堆if else来判断当前是什么状态。
这样一来,当状态需要增加修改删除时,就会非常麻烦,一堆if else能把你看晕。

经典的状态模式将状态封装成类,实现统一接口。
接口将规定状态将要执行什么行为,
当前状态的行为会导致对象的当前状态的改变。

对了,我曾经也见到过其他的状态模式,较经典状态模式有较大改变:
Finite State Machine in Unity

下面是经典状态模式的UML类图:
「设计模式笔记」状态模式_第1张图片
是不是很像策略模式?
不过,策略模式只是在你需要使用函数时提供具体函数,
那么你就要在Context类使用策略时,
主动选择使用那个策略。
而状态模式是自行通过行为改变状态,
并根据状态提供当前的行为。

状态模式对"开闭原则"的支持不太好,
对于可以切换状态的状态模式,
增加新的状态类需要修改那些负责状态转换的代码,
而且修改某个状态类的行为也需修改对应类的源代码。

UML示例

「设计模式笔记」状态模式_第2张图片
猪这种动物一般吃了睡睡了吃,
所以猪只有两种状态。
猪吃完之后,就会想睡,睡醒之后,就会想吃,
这就构成了状态的切换。

代码示例

State.h:

#pragma once
#include 
//C++是先编译后链接,要是两个头文件互相include,会出现循环引用,所以在其中一个类里不包含另一个类的头文件,而是用Class先声明。
//在用到另一个类内容的.cpp文件中再include它的头文件。
class Pig;
class State
{
protected:
	Pig* AimPig = nullptr;
public:
	State(Pig* aimPig);
	virtual void Handle() = 0;
};
class Eating :
	public State
{
public:
	Eating(Pig* aimPig) :State(aimPig) {}
	virtual void Handle() override;
};
class Sleeping :
	public State
{
public:
	Sleeping(Pig* aimPig) :State(aimPig) {}
	virtual void Handle() override;
};

Pig.h:

#pragma once
#include "State.h"
class Pig
{
private:
	State* EatingState;
	State* SleepingState;
	State* CurrentState;
public:
	Pig();
	~Pig();
	void Action();
	void SetState(State* state);
	State* GetEatingState();
	State* GetSleepingState();
};

Pig.cpp:

#include "Pig.h"
Pig::Pig()
{
	EatingState = new Eating(this);
	SleepingState = new Sleeping(this);
	CurrentState = EatingState;
}
Pig::~Pig()
{
	delete EatingState;
	delete SleepingState;
}
void Pig::Action()
{
	CurrentState->Handle();
}
void Pig::SetState(State* state)
{
	CurrentState = state;
}
State* Pig::GetEatingState()
{
	return EatingState;
}
State* Pig::GetSleepingState()
{
	return SleepingState;
}

State.cpp:

#include "State.h"
#include "Pig.h"
State::State(Pig* aimPig)
{
	AimPig = aimPig;
}
void Eating::Handle()
{
	std::cout << "I`m eating..." << std::endl;
	AimPig->SetState(AimPig->GetSleepingState());
}
void Sleeping::Handle()
{
	std::cout << "shushhhhhhhhhhhh..." << std::endl;
	AimPig->SetState(AimPig->GetEatingState());
}

Main.cpp:

#include 
#include "Pig.h"
#include "State.h"
int main()
{
	Pig pig;
	pig.Action();
	pig.Action();
	pig.Action();
	pig.Action();
	pig.Action();
	pig.Action();
	pig.Action();
	pig.Action();
	pig.Action();
}

「设计模式笔记」状态模式_第3张图片

你可能感兴趣的:(设计模式学习笔记)