目录
1 状态模式介绍
状态模式(state pattern)的定义: 允许一个对象在其内部状态改变时改变它的行为. 对象看起来似乎修改了它的类.
2 状态模式结构
3 状态模式实现
/**
* 抽象状态接口
* @author spikeCong
* @date 2022/10/17
**/
public interface State {
//声明抽象方法,不同具体状态类可以有不同实现
void handle(Context context);
}
/**
* 上下文类
* @author spikeCong
* @date 2022/10/17
**/
public class Context {
private State currentState; //维持一个对状态对象的引用
public Context() {
this.currentState = null;
}
public State getCurrentState() {
return currentState;
}
public void setCurrentState(State currentState) {
this.currentState = currentState;
}
@Override
public String toString() {
return "Context{" +
"currentState=" + currentState +
'}';
}
}
public class ConcreteStateA implements State {
@Override
public void handle(Context context) {
System.out.println("进入状态模式A......");
context.setCurrentState(this);
}
@Override
public String toString() {
return "当前状态: ConcreteStateA";
}
}
public class ConcreteStateB implements State{
@Override
public void handle(Context context) {
System.out.println("进入状态模式B......");
context.setCurrentState(this);
}
@Override
public String toString() {
return "当前状态: ConcreteStateB";
}
}
public class Client {
public static void main(String[] args) {
Context context = new Context();
State state1 = new ConcreteStateA();
state1.handle(context);
System.out.println(context.getCurrentState().toString());
System.out.println("========================");
State state2 = new ConcreteStateB();
state2.handle(context);
System.out.println(context.getCurrentState().toString());
}
}
4 状态模式应用实例
1) 不使用设计模式
/**
* 交通灯类
* 红灯(禁行) ,黄灯(警示),绿灯(通行) 三种状态.
* @author spikeCong
* @date 2022/10/17
**/
public class TrafficLight {
//初始状态红灯
private String state = "红";
//切换为绿灯(通行)状态
public void switchToGreen(){
if("绿".equals(state)){//当前是绿灯
System.out.println("当前为绿灯状态,无需切换!");
}else if("红".equals(state)){
System.out.println("红灯不能切换为绿灯!");
}else if("黄".equals(state)){
state = "绿";
System.out.println("绿灯亮起...时长: 60秒");
}
}
//切换为黄灯(警示)状态
public void switchToYellow(){
if("黄".equals(state)){//当前是黄灯
System.out.println("当前为黄灯状态,无需切换!");
}else if("红".equals(state) || "绿".equals(state)){
state = "黄";
System.out.println("黄灯亮起...时长:10秒");
}
}
//切换为黄灯(警示)状态
public void switchToRed(){
if("红".equals(state)){//当前是绿灯
System.out.println("当前为红灯状态,无需切换!");
}else if("绿".equals(state)){
System.out.println("绿灯不能切换为红灯!");
}else if("黄".equals(state)){
state = "红";
System.out.println("红灯亮起...时长: 90秒");
}
}
}
2) 使用状态模式,将交通灯的切换逻辑组织起来,把跟状态有关的内容从交通灯类里抽离出来,使用类来表示不同的状态.
/**
* 交通灯类
* 红灯(禁行) ,黄灯(警示),绿灯(通行) 三种状态.
* @author spikeCong
* @date 2022/10/17
**/
public class TrafficLight {
//初始状态红灯
State state = new Red();
public void setState(State state) {
this.state = state;
}
//切换为绿灯状态
public void switchToGreen(){
state.switchToGreen(this);
}
//切换为黄灯状态
public void switchToYellow(){
state.switchToYellow(this);
}
//切换为红灯状态
public void switchToRed(){
state.switchToRed(this);
}
}
/**
* 交通灯状态接口
* @author spikeCong
* @date 2022/10/17
**/
public interface State {
void switchToGreen(TrafficLight trafficLight); //切换为绿灯
void switchToYellow(TrafficLight trafficLight); //切换为黄灯
void switchToRed(TrafficLight trafficLight); //切换为红灯
}
/**
* 红灯状态类
* @author spikeCong
* @date 2022/10/17
**/
public class Red implements State {
@Override
public void switchToGreen(TrafficLight trafficLight) {
System.out.println("红灯不能切换为绿灯!");
}
@Override
public void switchToYellow(TrafficLight trafficLight) {
System.out.println("黄灯亮起...时长:10秒!");
}
@Override
public void switchToRed(TrafficLight trafficLight) {
System.out.println("已是红灯状态无须再切换!");
}
}
/**
* 绿灯状态类
* @author spikeCong
* @date 2022/10/17
**/
public class Green implements State {
@Override
public void switchToGreen(TrafficLight trafficLight) {
System.out.println("已是绿灯无须切换!");
}
@Override
public void switchToYellow(TrafficLight trafficLight) {
System.out.println("黄灯亮起...时长:10秒!");
}
@Override
public void switchToRed(TrafficLight trafficLight) {
System.out.println("绿灯不能切换为红灯!");
}
}
/**
* 黄灯状态类
* @author spikeCong
* @date 2022/10/17
**/
public class Yellow implements State {
@Override
public void switchToGreen(TrafficLight trafficLight) {
System.out.println("绿灯亮起...时长:60秒!");
}
@Override
public void switchToYellow(TrafficLight trafficLight) {
System.out.println("已是黄灯无须切换!");
}
@Override
public void switchToRed(TrafficLight trafficLight) {
System.out.println("红灯亮起...时长:90秒!");
}
}
public class Client {
public static void main(String[] args) {
TrafficLight trafficLight = new TrafficLight();
trafficLight.switchToYellow();
trafficLight.switchToGreen();
trafficLight.switchToRed();
}
}
5 状态模式总结
1) 状态模式的优点:
- 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
- 允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
2) 状态模式的缺点:
- 状态模式的使用必然会增加系统类和对象的个数。
- 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
- 状态模式对"开闭原则"的支持并不太好 (添加新的状态类需要修改那些负责状态转换的源代码)。
3) 状态模式常见的使用场景:
- 对象根据自身状态的变化来进行不同行为的操作时, 比如,购物订单状态。
- 对象需要根据自身变量的当前值改变行为,不期望使用大量 if-else 语句时, 比如,商品库存状态。
- 对于某些确定的状态和行为,不想使用重复代码时, 比如,某一个会员当天的购物浏览记录。