C++设计模式-状态模式详解

版权声明:本文为博主原创文章,未经同意不允许转载! https://blog.csdn.net/wb175208/article/details/85239414

状态模式:当一个对象内在状态改变时允许改变其行为,看起来像改变了棋类。

状态模式,顾名思义就是表示一个对象的状态,并且这些状态不一定是互斥的,常见的比如手机状态,有开机、关机、没有信号、正在通话。这四种状态中,比如手机处于关机状态时,就不能进行通话,只能进行开机;手机没有信号的时候,就不能进行打电话,只能进行关机;当手机出于开机状态的时候,手机可以没有信号也可以关机等。

所以手机不同的状态就会有不同状态下的行为,而且可以在不同的状态下进行切换。

那么根据以上状态可以搭建不同的手机使用场景。

首先定义手机的四种状态:

enum PHONESTATE{
	STATE_POWERON,//开机
	STATE_POWEROFF,//关机
	STATE_NOSIGNAL,//没有信号
	STATE_CALLING,//通话中
};

定义手机:

class MyPhone {
public:
	void setPhoneState(PHONESTATE state);
	PHONESTATE getPhoneState();

	void powerOn();
	void powerOff();
	void calling();
	void nosignal();

private:
	PHONESTATE _phoneState;
};

void MyPhone::setPhoneState(PHONESTATE state) {
	_phoneState = state;
}

PHONESTATE MyPhone::getPhoneState() {
	return _phoneState;
}

void MyPhone::powerOn() {
	switch(_phoneState) {
	case STATE_POWERON:
	printf("当前开机状态:不能再开机了!\n");
	break;
	case STATE_POWEROFF:
	printf("当前关机状态:当然可以开机了!\n");
	break;
	case STATE_NOSIGNAL:
	printf("当前手机没有信号:手机自然是开机状态,不能再次开机!\n");
	break;
	case STATE_CALLING:
	printf("当前手机正在通话:现在已经是开机状态!\n");
	break;
	default:
	break;
	}
}

void MyPhone::powerOff() {
	switch(_phoneState) {
	case STATE_POWERON:
	printf("当前开机状态:当然可以关机了!\n");
	break;
	case STATE_POWEROFF:
	printf("当前关机状态:不能再关机了!\n");
	break;
	case STATE_NOSIGNAL:
	printf("当前手机没有信号:当然可以关机了!\n");
	break;
	case STATE_CALLING:
	printf("当前手机正在通话:不可以关机!\n");
	break;
	default:
	break;
	}
}

void MyPhone::calling() {
	switch(_phoneState) {
	case STATE_POWERON:
	printf("当前开机状态:手机正在打电话!\n");
	break;
	case STATE_POWEROFF:
	printf("当前关机状态:不能打电话!\n");
	break;
	case STATE_NOSIGNAL:
	printf("当前手机没有信号:不可以打电话!\n");
	break;
	case STATE_CALLING:
	printf("当前手机正在通话:现在已经是通话状态!\n");
	break;
	default:
	break;
	}
}

void MyPhone::nosignal() {
	switch(_phoneState) {
	case STATE_POWERON:
	printf("当前开机状态:手机没有信号!\n");
	break;
	case STATE_POWEROFF:
	printf("当前关机状态:不知道信号怎么样!\n");
	break;
	case STATE_NOSIGNAL:
	printf("当前手机没有信号:...\n");
	break;
	case STATE_CALLING:
	printf("当前手机正在通话:手机没有信号了,通话中断!\n");
	break;
	default:
	break;
	}
}

使用场景:

int main() {

	MyPhone* myPhone = new MyPhone;
	myPhone->setPhoneState(STATE_POWEROFF);

	myPhone->powerOff();
	myPhone->powerOn();
	myPhone->calling();

	myPhone->setPhoneState(STATE_NOSIGNAL);
	myPhone->powerOn();
	myPhone->powerOff();
	myPhone->calling();
	myPhone->nosignal();
	return 0;
}

运行结果:
在这里插入图片描述

上面实现的手机在不同的状态下可以做的事情,使用大量的swich…case语句,如果要添加新的手机装填呢?比如手机信号弱等,是不是要重新每一个函数并且添加新的case语句,这就破坏了开闭原则。

有没有更好的办法呢?

答案是有的,咱们可以把手机不通状态提取出来,封装成公共的接口。

class IPhoneState {
public:
	IPhoneState();
	~IPhoneState();

	//关机
	virtual void powerOff() = 0;

	//开机
	virtual void powerOn() = 0;

	//没有信号
	virtual void onSignal() = 0;

	//正在通话中
	virtual void calling() = 0;
};

上面定义的函数是纯虚函数,子类必须继承实现的。

定义不通的状态子类。
开机状态:

//开机状态
class statePowerOn :public IPhoneState {
public:
	void powerOff()override;

	void powerOn()override;

	void onSignal()override;

	void calling()override;
};
void statePowerOn::powerOff() {
	printf("当前开机状态:当然可以关机了!\n");
}

void statePowerOn::powerOn() {
	printf("当前开机状态:不能再开机了!\n");

}

void statePowerOn::onSignal() {
	printf("当前开机状态:手机没有信号!\n");

}

void statePowerOn::calling() {
	printf("当前开机状态:手机正在打电话!\n");

}

关机状态:

//关机状态
class statePowerOff :public IPhoneState {
public:
	void powerOff()override;

	void powerOn()override;

	void onSignal()override;

	void calling()override;
};

void statePowerOff::powerOff() {
	printf("当前关机状态:不能再关机了!\n");

}

void statePowerOff::powerOn() {
	printf("当前关机状态:当然可以开机了!\n");

}

void statePowerOff::onSignal() {
	printf("当前关机状态:不知道信号怎么样!\n");
}

void statePowerOff::calling() {
	printf("当前关机状态:不能打电话!\n");

}

没有信号状态:

//没有信号状态
class stateNoSignal :public IPhoneState {
public:
	void powerOff()override;

	void powerOn()override;

	void onSignal()override;

	void calling()override;
};
void stateNoSignal::powerOff() {
	printf("当前手机没有信号:当然可以关机了!\n");

}

void stateNoSignal::powerOn() {
	printf("当前手机没有信号:手机自然是开机状态,不能再次开机!\n");
}

void stateNoSignal::onSignal() {
	printf("当前手机没有信号:...\n");

}

void stateNoSignal::calling() {
	printf("当前手机没有信号:不可以打电话!\n");

}

通话状态:

//通话状态
class stateCalling :public IPhoneState {
public:
	void powerOff()override;

	void powerOn()override;

	void onSignal()override;

	void calling()override;
};
void stateCalling::powerOff() {
	printf("当前手机正在通话:不可以关机!\n");

}

void stateCalling::powerOn() {
	printf("当前手机正在通话:现在已经是开机状态!\n");

}

void stateCalling::onSignal() {
	printf("当前手机正在通话:手机没有信号了,通话中断!\n");

}

void stateCalling::calling() {
	printf("当前手机正在通话:现在已经是通话状态!\n");

}

使用场景:

int main() {
	Phone* phone = new Phone;
	phone->setPhoneState(new statePowerOff());

	phone->powerOff();
	phone->powerOn();
	phone->calling();

	phone->setPhoneState(new stateNoSignal());
	phone->powerOn();
	phone->powerOff();
	phone->calling();
	phone->nosignal();

	return 0;
}

运行结果:
在这里插入图片描述

运行结果和之前使用case语句是一样的,而且结构很清楚。

状态模式的优点:
1.避免使用过多的switch…case语句,提高系统的可维护性;
2.很好的体现开闭原则和单一职责原则,每个状态都是一个子类;

猜你喜欢

转载自blog.csdn.net/wb175208/article/details/85239414