案例
假如我们接到一个研发做饭机器人的需求,需求比较简单,这个机器人只会做三件事:走路,做饭,关机。做每件事都有前提条件,只有在开机状态下才能走路,做饭和关机,类似的,在做饭状态下可以进行走路或者继续做饭。
拿到需求分析后,一种简单的设计和实现是,设计一个类,此类有走路、做饭和关机的方法,在执行方法前,用 if 或者 switch 语句判断当前机器人的状态是否运行执行。这种把状态和方法耦合在一起再加上分支条件判断的方案,代码会随着需求的变化复杂度会增加而且难以维护。
有没有有一种设计方案,符合开闭原则-面向新增开放,面向修改关闭
的原则,当机器人增加状态时,原有代码设计不做改动,只新增类或相关代码。答案是有的,就是我们即将讲解的状态模式。
状态模式
状态模式的核心思想是把一个对象的状态和行为分开,用不同的接口或类去定义,用状态去限制该对象的行为,行为变化时相应的状态可能也发生变化。
主要参与者如下图:
Context
- 对外提供对象的主要行为方法
- 维护一个具体的状态实例为当前状态
Sate
- 状态接口,主要来封装某种状态下的行为方法实现
ConcreteState
- 接口State 的实现类,代表某个具体状态的实现
用状态模式实现
接口 RoboticState
封装了机器人的行为,也就是上面的提到的 State 角色
public interface RoboticState {
public void walk();
public void cook();
public void off();
}
类Robot
实现了接口 RoboticState , 扮演了 Context 角色,包含了一系列状态熟悉和当前状态属性。
public class Robot implements RoboticState{
private RoboticState roboticOn;
private RoboticState roboticCook;
private RoboticState roboticOff;
private RoboticState state;
public Robot(){
this.roboticOn = new RoboticOn(this);
this.roboticCook = new RoboticCook(this);
this.roboticOff = new RoboticOff(this);
this.state = roboticOn;
}
public void setRoboticState(RoboticState state){
this.state = state;
}
@Override
public void walk() {
state.walk();
}
@Override
public void cook() {
state.cook();
}
@Override
public void off() {
state.off();
}
public RoboticState getRoboticOn() {
return roboticOn;
}
public void setRoboticOn(RoboticState roboticOn) {
this.roboticOn = roboticOn;
}
public RoboticState getRoboticCook() {
return roboticCook;
}
public void setRoboticCook(RoboticState roboticCook) {
this.roboticCook = roboticCook;
}
public RoboticState getRoboticOff() {
return roboticOff;
}
public void setRoboticOff(RoboticState roboticOff) {
this.roboticOff = roboticOff;
}
public RoboticState getState() {
return state;
}
public void setState(RoboticState state) {
this.state = state;
}
}
开机状态实现类 RoboticOn
public class RoboticOn implements RoboticState{
private final Robot robot;
public RoboticOn(Robot robot){
this.robot = robot;
}
@Override
public void walk() {
System.out.println("Walking...");
}
@Override
public void cook() {
System.out.println("Cooking...");
robot.setRoboticState(robot.getRoboticCook());
}
@Override
public void off() {
robot.setState(robot.getRoboticOff());
System.out.println("Robot is switched off");
}
}
做饭状态实现类 RoboticCook
public class RoboticCook implements RoboticState{
private final Robot robot;
public RoboticCook(Robot robot){
this.robot = robot;
}
@Override
public void walk() {
System.out.println("Walking...");
robot.setRoboticState(robot.getRoboticOn());
}
@Override
public void cook() {
System.out.println("Cooking...");
}
@Override
public void off() {
System.out.println("Cannot switched off while cooking...");
}
}
关机状态实现类 RoboticOff
public class RoboticOff implements RoboticState{
private final Robot robot;
public RoboticOff(Robot robot){
this.robot = robot;
}
@Override
public void walk() {
System.out.println("Walking...");
robot.setRoboticState(robot.getRoboticOn());
}
@Override
public void cook() {
System.out.println("Cannot cook at Off state.");
}
@Override
public void off() {
System.out.println("Already switched off...");
}
}
测试代码
public class TestStatePattern {
public static void main(String[] args) {
Robot robot = new Robot();
robot.walk();
robot.cook();
robot.walk();
robot.off();
robot.walk();
robot.off();
robot.cook();
}
}
输出结果
Walking…
Cooking…
Walking…
Robot is switched off Walking…
Robot is switched off Cannot cook at Off state.
如果此时新增一个待机的需求,该怎么办呢?新增待机状态类 RoboticStandby
public class RoboticStandby implements RoboticState{
private final Robot robot;
public RoboticStandby(Robot robot){
this.robot = robot;
}
@Override
public void walk() {
System.out.println("In standby state...");
robot.setState(robot.getRoboticOn());
System.out.println("Walking...");
}
@Override
public void cook() {
System.out.println("In standby state...");
robot.setRoboticState(robot.getRoboticCook());
System.out.println("Cooking...");
}
@Override
public void off() {
System.out.println("In standby state...");
robot.setState(robot.getRoboticOff());
System.out.println("Robot is switched off");
}
}
类 Robot
新增一个待机状态,代码如下
public class Robot implements RoboticState{
private RoboticState roboticOn;
private RoboticState roboticCook;
private RoboticState roboticOff;
private RoboticState roboticStandby;
private RoboticState state;
public Robot(){
this.roboticOn = new RoboticOn(this);
this.roboticCook = new RoboticCook(this);
this.roboticOff = new RoboticOff(this);
this.roboticStandby = new RoboticStandby(this);
this.state = roboticOn;
}
public void setRoboticState(RoboticState state){
this.state = state;
}
@Override
public void walk() {
state.walk();
setState(getRoboticStandby());
}
@Override
public void cook() {
state.cook();
setState(getRoboticStandby());
}
@Override
public void off() {
state.off();
}
public RoboticState getRoboticOn() {
return roboticOn;
}
public void setRoboticOn(RoboticState roboticOn) {
this.roboticOn = roboticOn;
}
public RoboticState getRoboticCook() {
return roboticCook;
}
public void setRoboticCook(RoboticState roboticCook) {
this.roboticCook = roboticCook;
}
public RoboticState getRoboticOff() {
return roboticOff;
}
public void setRoboticOff(RoboticState roboticOff) {
this.roboticOff = roboticOff;
}
public RoboticState getState() {
return state;
}
public void setState(RoboticState state) {
this.state = state;
}
public RoboticState getRoboticStandby() {
return roboticStandby;
}
public void setRoboticStandby(RoboticState roboticStandby) {
this.roboticStandby = roboticStandby;
}
}