[C++] State Pattern 实作

状态模式(State Pattern)属于行为型模式

在状态模式下,在情境中的一个对象可执行的行为会随着状态对象的改变而变化,因此状态模式又被归类为行为型模式。


适合使用此模式的情况:

1. 某对象的行为随着自身状态的改变而改变。

2. 以多重条件分支语句规范一个对象在不同状态下可执行的行为。


使用状态模式的优点

1. 将与状态有关的一系列行为抽象出来作为一个State接口类,然后就可以根据不同的状态新增ConcreteState实现类,并封装不同的行为到类中。
    简单来说,就是以状态区分不同的行为。

2. 状态转换逻辑可以封装在ConcreteState类中,从而减少大量条件语句。

3. 通过定义新的ConcreteState类就可以增加新的状态及转换逻辑。


使用状态模式的缺点

1. 由于需要以状态区分行为,故整个系统中的类必定会增加。

2. 系统需求必须分析清楚,否则采用状态模式反而会造成系统结构混乱。

3. 状态模式并不完全符合"开闭原则"(Open-Closed Principle),对于把状态转换封装在状态类中的状态模式而言,系统中一旦加入了新的状态类,就需要修改原先的状态转换代码,否则将无法转换到新的状态。修改某个状态的行为也需要修改对应​​状态类的代码。



以下是呈现状态模式的类别图



比较:

若是回忆一下会发现,怎么状态模式和策略模式那么像?

其实这两者可应用的场合十分类似,模式结构也都一样,只不过两者所关注的焦点不相同,

策略模式关注的是把算法(Algorithm)或行为(Behavior)封装在策略族中的一个实体类,Context的行为则委托给该实体类的实例执行

状态模式关注的是状态族中的实体之间可以轻松转换


简单来说

策略模式关注的是行为的封装

状态模式关注的则是状态间的转换


以下是代码示例。


本篇文章实作的应用情境如下:

现有一手机。

手机有两种状态:开机、关机。

可对手机执行两种操作:开关机、打电话。

手机在不同状态下可表现的行为都不同。


示例代码如下:


状态类interface

[PhoneState.h]

// State interface
#pragma once
#include "stdio.h"
#include "MobilePhoneContext.h"


class MobilePhoneContext;

class PhoneState
{
public:
	PhoneState(void){};
	~PhoneState(void){};
	virtual void changePowerState(MobilePhoneContext *context) = 0; // change the power mode
	virtual void call() = 0; // make a phone call
};



状态实现类(开关机状态)

[OnState.h]

#pragma once
#include "PhoneState.h"
#include "OffState.h"


class OnState :
	public PhoneState
{
public:
	OnState(void){};
	~OnState(void){};
	void changePowerState(MobilePhoneContext *context); // change the power mode
	void call(); // make a phone call
};

[OnState.cpp]

#include "OnState.h"


void OnState::changePowerState(MobilePhoneContext *context)
{
	context->setState(new OffState());
}

void OnState::call()
{
	printf("Call my girlfriend.\n");
}


[OffState.h]

#pragma once
#include "PhoneState.h"
#include "OnState.h"


class OffState :
	public PhoneState
{
public:
	OffState(void){};
	~OffState(void){};
	void changePowerState(MobilePhoneContext *context); // change the power mode
	void call(); // make a phone call
};

[OffState.cpp]

#include "OffState.h"


void OffState::changePowerState(MobilePhoneContext *context)
{
	context->setState(new OnState());
}

void OffState::call()
{
	printf("The power is off!! It can't make a call.\n");
}



情境类(手机)

[MobilePhoneContext.h]

// Context
#pragma once
#include "PhoneState.h"


class PhoneState;

class MobilePhoneContext
{
public:
	MobilePhoneContext(void);
	MobilePhoneContext(PhoneState *state);
	~MobilePhoneContext(void);
	void setState(PhoneState *state);
	void pressPower();
	void call();
private:
	PhoneState *state;
};

[MobilePhoneContext.cpp]

#include "MobilePhoneContext.h"
#include "OffState.h"

MobilePhoneContext::MobilePhoneContext(void)
{
	this->state = new OffState();
}

MobilePhoneContext::MobilePhoneContext(PhoneState *state)
{
	this->state = state;
}

MobilePhoneContext::~MobilePhoneContext(void)
{
	delete this->state;
}

void MobilePhoneContext::setState(PhoneState *state)
{
	this->state = state;
}

void MobilePhoneContext::pressPower()
{
	state->changePowerState(this); // 状态的切换可以在ConcreteState类中指定,也可以在Context中根据条件指定state指向的ConcreteState类,本示例中采用的方法是前者。
}

void MobilePhoneContext::call()
{
	state->call();
}



主程序

[StatePatternDemo.cpp]

#include "MobilePhoneContext.h"
#include "PhoneState.h"
#include "OffState.h"

void main()
{
	MobilePhoneContext *phone = new MobilePhoneContext(new OffState());

	phone->call();
	phone->pressPower();
	phone->call();
	phone->pressPower();
	phone->call();

	getchar();
	return;
}


Output

The power is off!! It can't make a call.
Call my girlfriend.
The power is off!! It can't make a call.


工程就不打包了,程序没有很复杂,应该很容易看明白,

之所以把关键部分类定义和实现分开,是希望能够将设计模式观念明确,也希望能够养成良好编程习惯。





  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值