【设计模式】状态模式

说明

状态模式和策略模式比较相似,都是将算法抽象出来成为独立的类。但是相比策略模式,状态模式下的独立类中间存在着内在的联系。

引用《Head First: Design Patterns》中的原话:

A little known fact: the Strategy and State Patterns were twins separated at birth.  As you know, the Strategy Pattern went on to create a wildly successful business around interchangeable algorithms.  State, however, took the perhaps more noble path of helping objects to control their behavior by changing their internal state. He’s often overheard telling his object clients, “Just repeat after me: I’m good enough, I’m smart enough, and doggonit...”

下面是一个例子:

上例中,Gun有两种状态,一种是有子弹的,一种是没有子弹的。

当Character使用Gun时,会遇到两种情况,即上面说的有子弹和没有子弹两种情况。且两种情况交替出现。

这里使用了Gun的两种状态,并包装了它们使用时的算法,这样Character就不需要直接去关注两种情况的不同,反正直接使用就可以了。

下面是具体的代码:

1. Character类:

/****************** Character声明 ********************/
class Character {
private:
	//Gun的两种状态
	Gun *hasBulletsState;
	Gun *noBulletsState;
	//currentState可以是上面的任意一种
	Gun *currentState;
public:
	//构造函数
	Character();
	//获取和设置状态的函数
	Gun * getNoBulletsState();
	Gun * getHasBulletsState();
	void setState(Gun *gs);
	//主函数
	void useGun();
};

2. Character类的实现:

/****************** Character定义 ********************/
Character::Character() {
	//初始化时就要确定所有的状态
	hasBulletsState = new HasBulletsGun();
	hasBulletsState->setOwner(this);
	hasBulletsState->setBullets(BULLETS_SIZE);
	noBulletsState = new NoBulletsGun();
	noBulletsState->setOwner(this);
	this->currentState = hasBulletsState;
}
Gun * Character::getNoBulletsState() {
	return this->noBulletsState;
}
Gun * Character::getHasBulletsState() {
	return this->hasBulletsState;
}
void Character::setState(Gun *gs) {
	this->currentState = gs;
}
void Character::useGun() {
	currentState->active();
}

3. Gun类及其定义:

/****************** Gun声明 ********************/
class Gun {
private:
	Character *owner;
	int bulletsCount;
public:
	void setOwner(Character *ch);
	Character *getOwner();
	void setBullets(int count);
	int getBullets();
	void fire();
	virtual void active();
};

/****************** Gun定义 ********************/
void Gun::active() {
	cout << "Gun active." << endl;
}
void Gun::setBullets(int count) {
	this->bulletsCount = count;
}
int Gun::getBullets() {
	return this->bulletsCount;
}
void Gun::fire() {
	this->bulletsCount--;
	cout << "Fire one bullet. Bullets left: " << this->bulletsCount << endl;
}
Character *Gun::getOwner() {
	return this->owner;
}
void Gun::setOwner(Character *ch) {
	this->owner = ch;
}

4. Gun的子类状态:

/****************** HasBulletsGun定义 ********************/
class HasBulletsGun : public Gun {
public:
	void active() override;
};
void HasBulletsGun::active() {
	fire();
	if (getBullets() == 0) {
		getOwner()->setState(getOwner()->getNoBulletsState());
	}
}

/****************** NoBulletsGun定义 ********************/
class NoBulletsGun : public Gun {
public:
	void active() override;
};
void NoBulletsGun::active() {
	cout << "No bullets left. Setting bullets... " << endl;
	getOwner()->getHasBulletsState()->setBullets(BULLETS_SIZE);
	getOwner()->setState(getOwner()->getHasBulletsState());
	cout << "Done" << endl;
}

5. 测试代码:

/****************** 测试 ********************/
int main(void) {
	Character *ch = new Character();
	for (int i = 0; i < 10; i++) {<span style="white-space:pre">	</span>//开枪10次,中间会有重新装弹的过程
		ch->useGun();
	}
	return 0;
}

6. 下面是测试结果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值