学而不思则罔,思而不学则殆。 ——孔子
一、状态模式简介
状态模式是设计模式中行为型模式的一种。一个对象在它的状态改变时,它的行为也随之改变,看起来好像改变了其类。
二、举例说明
假如电话有三种状态:通话中、待机中、已关机。四种行为:打电话、挂电话、开机、关机。那么在不同的状态下这四种行为的表现方式肯定不同。例如关机状态下不能打电话,而待机状态下就可以打电话。
三、代码实现
1、不使用状态模式的实现方法
/**
* 不使用状态模式的实现方式
*
* @author ZhengNC
* @date 2020/9/22 16:48
*/
public class NotUsedStatePattern {
enum State{
/** 通话中 */
Calling,
/** 待机中 */
Standby,
/** 已关机 */
Shutdown
}
private State state = State.Shutdown;
/**
* 打电话
*/
public void call() {
switch (state){
case Calling:
System.out.println("正在通话中,不能发起新的通话。。。");
break;
case Standby:
state = State.Calling;
break;
case Shutdown:
System.out.println("手机已关机,无法通话!");
break;
default:
break;
}
}
/**
* 挂电话
*/
public void bye() {
switch (state){
case Calling:
state = State.Standby;
break;
case Standby:
System.out.println("不在通话状态,无需挂断!");
break;
case Shutdown:
System.out.println("手机已关机,不需挂断!");
break;
default:
break;
}
}
/**
* 关机
*/
public void shutdown() {
switch (state){
case Calling:
System.out.println("通话中,正在强制关机。。。");
state = State.Shutdown;
break;
case Standby:
state = State.Shutdown;
break;
case Shutdown:
System.out.println("手机已关机,不需重复关机!");
break;
default:
break;
}
}
/**
* 开机
*/
public void bootUp() {
switch (state){
case Calling:
System.out.println("手机已经开机了,无需重复开机。");
break;
case Standby:
System.out.println("手机已经开机了,无需重复开机。");
break;
case Shutdown:
state = State.Standby;
break;
default:
break;
}
}
}
从以上代码中可以发现,类中的逻辑过于复杂,而且如果要增加一种状态的话将需要修改每个行为对应的方法。
2、使用状态模式的实现方法
PhoneAction(电话动作):
/**
* 电话动作
*
* @author ZhengNC
* @date 2020/9/22 15:36
*/
public interface PhoneAction {
/**
* 通话
*/
void call();
/**
* 挂掉电话
*/
void bye();
/**
* 关机
*/
void shutdown();
/**
* 开机
*/
void bootUp();
}
PhoneState(手机状态):
/**
* 手机状态
*
* @author ZhengNC
* @date 2020/9/22 15:20
*/
public abstract class PhoneState implements PhoneAction {
protected Phone phone;
protected String stateName;
public PhoneState(Phone phone){
this.phone = phone;
}
@Override
public String toString() {
return "状态:"+stateName;
}
}
Calling(状态:通话中):
/**
* 状态:通话中
*
* @author ZhengNC
* @date 2020/9/22 15:54
*/
public class Calling extends PhoneState {
public Calling(Phone phone) {
super(phone);
stateName = "通话中";
}
@Override
public void call() {
System.out.println("正在通话中,不能发起新的通话。。。");
}
@Override
public void bye() {
phone.setState(phone.getStandby());
}
@Override
public void shutdown() {
System.out.println("通话中,正在强制关机。。。");
phone.setState(phone.getShutdown());
}
@Override
public void bootUp() {
System.out.println("手机已经开机了,无需重复开机。");
}
}
Shutdown(状态:已关机):
/**
* 状态:已关机
*
* @author ZhengNC
* @date 2020/9/22 16:13
*/
public class Shutdown extends PhoneState {
public Shutdown(Phone phone) {
super(phone);
stateName = "已关机";
}
@Override
public void call() {
System.out.println("手机已关机,无法通话!");
}
@Override
public void bye() {
System.out.println("手机已关机,不需挂断!");
}
@Override
public void shutdown() {
System.out.println("手机已关机,不需重复关机!");
}
@Override
public void bootUp() {
phone.setState(phone.getStandby());
}
}
Standby(状态:待机中):
/**
* 状态:待机中
*
* @author ZhengNC
* @date 2020/9/22 16:00
*/
public class Standby extends PhoneState {
public Standby(Phone phone) {
super(phone);
stateName = "待机中";
}
@Override
public void call() {
phone.setState(phone.getCalling());
}
@Override
public void bye() {
System.out.println("不在通话状态,无需挂断!");
}
@Override
public void shutdown() {
phone.setState(phone.getShutdown());
}
@Override
public void bootUp() {
System.out.println("手机已经开机了,无需重复开机。");
}
}
Phone(电话):
/**
* 电话
*
* @author ZhengNC
* @date 2020/9/22 15:24
*/
public class Phone implements PhoneAction {
/**
* 状态:通话中
*/
private final PhoneState Calling = new Calling(this);
/**
* 状态:待机中
*/
private final PhoneState standby = new Standby(this);
/**
* 状态:已关机
*/
private final PhoneState shutdown = new Shutdown(this);
/**
* 当前状态
*/
private PhoneState state = shutdown;
public PhoneState getCalling() {
return Calling;
}
public PhoneState getStandby() {
return standby;
}
public PhoneState getShutdown() {
return shutdown;
}
public PhoneState getState() {
return state;
}
public void setState(PhoneState state) {
this.state = state;
}
@Override
public void call() {
state.call();
}
@Override
public void bye() {
state.bye();
}
@Override
public void shutdown() {
state.shutdown();
}
@Override
public void bootUp() {
state.bootUp();
}
}
3、测试状态模式
/**
* 测试状态模式
*
* @author ZhengNC
* @date 2020/9/22 16:31
*/
public class TestState {
public static void main(String[] args) {
Phone phone = new Phone();
System.out.println(phone.getState());
phone.call();
System.out.println(phone.getState());
phone.bye();
System.out.println(phone.getState());
phone.bootUp();
System.out.println(phone.getState());
phone.call();
System.out.println(phone.getState());
phone.bye();
System.out.println(phone.getState());
phone.shutdown();
System.out.println(phone.getState());
}
}
输出结果:
状态:已关机
手机已关机,无法通话!
状态:已关机
手机已关机,不需挂断!
状态:已关机
状态:待机中
状态:通话中
状态:待机中
状态:已关机
四、与策略模式的区别
刚接触状态模式的时候肯定觉得和策略模式很像,但它们最大的区别就是策略模式的策略是手动选择的,而状态模式的状态却是对象自动变化的。