二十三种设计模式(二十一)--状态模式

状态模式(State)

状态模式用来解决多模式, 运行态很多伴随对应很多异常处理的场景

通常我们写业务逻辑需要切换的代码时, 会采用枚举 StateXXX的方式来定义当前某个对象所处的状态

比如摄像头初始化, 运行中, 休眠中, 异常等等状态

再比如线程状态, 初始化, 创建失败, 运行中, 等待中等等

采用一个state字段标记状态是第一反应的做法, 但是伴随很多问题, 有些细节没有考虑到对应的状态处理, 有些状态下容易和别的状态搞混, 程序中有大量的类似if(state ==xxx) else if (state== xxx)的代码

阅读起来困难, 多种状态下的复杂情况处理导致逻辑代码堆积如山

状态模式采用的方案是

  1. 写一个通用的接口或者抽象类, 在其中封装程序整体运行的所有步骤
  2. 子类为各种状态, 继承抽象类或实现对应接口, 处理该状态下各个步骤都应该怎么做
  3. 最终封装一个状态管理类, 处理实际业务逻辑, 切换各种状态, 对外提供简明的流程调用接口, 用户无需关心内部状态如何切换

下面以顾客到饭店点餐程序为例, 演示状态模式的具体实现:

java 复制代码
interface State {
    void order(OrderManager orderManager, String dishName);
    void cook(OrderManager orderManager);
    void deliver(OrderManager orderManager);
}

class OrderState implements State {
    @Override
    public void order(OrderManager orderManager, String dishName) {
        System.out.println("[info] 顾客点菜中: " + dishName);
        // 状态切换逻辑封装在内部
        orderManager.setState(new CookState());

    }

    @Override
    public void cook(OrderManager orderManager) {
        System.out.println("[error] 未点完菜, 不做菜");
    }

    @Override
    public void deliver(OrderManager orderManager) {
        System.out.println("[error] 未点完菜, 没有可以传送的菜品");
    }
}

class CookState implements State {
    @Override
    public void order(OrderManager orderManager, String dishName) {
        System.out.println("[warning] 厨师新来的, 拒绝加菜");
    }

    @Override
    public void cook(OrderManager orderManager) {
        System.out.println("[info] 做菜中 ");
        orderManager.setState(new DeliverState());
    }

    @Override
    public void deliver(OrderManager orderManager) {
        System.out.println("[error] 菜品未准备完成");
    }
}

class DeliverState implements State {
    @Override
    public void order(OrderManager orderManager, String dishName) {
        System.out.println("[warning] 传菜中, 吃完再加");
    }

    @Override
    public void cook(OrderManager orderManager) {
        System.out.println("[error] 菜已经做完, 没有加菜, 厨师已休息");
    }

    @Override
    public void deliver(OrderManager orderManager) {
        System.out.println("[info] 传菜中");
        orderManager.setState(new OrderState());
    }
}


class OrderManager {
    State state;

    OrderManager() {
        this.state = new OrderState();
    }

    // 提供给状态类内部调用的方法,用于切换状态
    void setState(State state) {
        this.state = state;
    }

    void customOrder(String dishName) {
        state.order(this, dishName);
    }

    void doCook() {
        state.cook(this);
    }

    void doDeliver() {
        state.deliver(this);
    }
}

调用

java 复制代码
public class StatePattern {
    public static void main(String[] args) {
    	// 调用端不知道manager内部处于什么状态, 只负责业务逻辑即可
        OrderManager manager = new OrderManager();
        System.out.println("=========== 点菜 ===========");
        manager.customOrder("鱼香肉丝");
        manager.doCook();
        manager.doDeliver();

    }
}

运行结果

复制代码
[info] 顾客点菜中: 鱼香肉丝
[info] 做菜中 
[info] 传菜中

以上实现有两个注意点, 格外注意

  1. 外部调用端不知道当前应用处于什么状态, 它只负责业务逻辑
  2. 状态实现类内部持有上下文对象, 即orderManager, 这样可以实现状态内部切换逻辑

这段代码不太好的地方是每次状态切换都new了新的状态, 实际运行时, 可以将状态封装为单例模式, 防止反复new出新的对象

相关推荐
星恒随风36 分钟前
C++ 类和对象入门(五):初始化列表、explicit 和 static 成员详解
开发语言·c++·笔记·学习·状态模式
艾利克斯冰1 小时前
Java 设计模式-行为型模式(更新中)
java·开发语言·设计模式
狼哥16861 小时前
蛋糕美食元服务_我的实现指南
ui·harmonyos
狼哥16861 小时前
蛋糕美食元服务_美食实现指南
ui·harmonyos
RReality2 小时前
【Unity UGUI】血条 / 进度条(HP Bar)
ui·unity·游戏引擎·图形渲染
狼哥16864 小时前
蛋糕美食元服务_地图实现指南
ui·harmonyos
UXbot5 小时前
AI网页开发工具能替代工具吗?5大平台对比
前端·人工智能·低代码·ui·原型模式·web app
星心源七境6 小时前
七境体系全解析:从六韬兵法到AI锁颜,一套贯穿古典智慧与现代应用的成长操作系统
人工智能·设计模式·设计
码农飞哥7 小时前
Spring Boot 多角色权限隔离实战:接口层+路由层+UI层三层防御,杜绝生产数据泄露
spring boot·状态模式·架构设计·系统设计·权限控制
qq_297574677 小时前
设计模式系列文章(基础篇第21篇):迭代器模式——遍历聚合解耦,实现统一迭代访问
设计模式·迭代器模式