您的位置:首页 > 其它

设计模式基础——状态模式

2016-02-01 17:04 197 查看
状态模式和策略模式比较相似,都是将算法抽象出来成为独立的类。但是相比策略模式,状态模式下的独立类中间存在着内在的联系。

引用《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. 下面是测试结果:

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