博客
关于我
设计模式(21)——状态模式
阅读量:557 次
发布时间:2019-03-09

本文共 5738 字,大约阅读时间需要 19 分钟。

APP抽奖活动状态模式设计与实现

状态模式概述

状态模式是一种设计模式,主要用于解决对象在不同状态下表现出不同的行为问题。通过将状态和行为分开管理,可以让对象在状态变化时灵活地展示不同的行为,实现更灵活的状态管理。

状态模式在抽奖活动中的应用

活动状态说明

抽奖活动可以处于以下四个状态:

  • 不能抽奖状态(NoRaffleState)

    • 用户未扣除积分或抽奖次数已用完。
    • 扣除积分后转换为可以抽奖的状态。
  • 可以抽奖状态(CanRaffleState)

    • 用户已经扣除积分,当前可以进行抽奖。
    • 抽奖后根据结果转换为发放奖品状态或不能抽奖状态。
  • 发放奖品状态(DispenseState)

    • 用户中奖后进入该状态。
    • 发放奖品后转换为不能抽奖状态。
  • 奖品发放完毕状态(DispenseOutState)

    • 所有奖品已发放,活动结束。
    • 用户无法再进行抽奖或扣除积分。
  • 状态转换关系

    • 从 NoRaffleState 转换到 CanRaffleState

      扣除积分成功后,用户可以抽奖。

    • 从 CanRaffleState 转换到 DispenseState 或 NoRaffleState

      抽奖成功则转换为 DispenseState,抽奖失败则转换为 NoRaffleState。

    • 从 DispenseState 转换到 NoRaffleState

      发放完毕后,用户无法继续抽奖。

    • 从 DispenseOutState 无法转换

    状态模式的实现类图

    • State 接口

      提供与上下文相关的基本操作,如扣除积分、抽奖、发放奖品。

    • ConcreteState 实现类

      定义具体的状态行为,如 CanRaffleState、NoRaffleState 等。

    • Context 类

      维护当前状态实例,提供状态切换的方法。

    具体实现代码

    状态接口定义

    package com.lm.state;
    public interface State {
    void deduceMoney();
    boolean raffle();
    void dispensePrize();
    }

    各状态实现类

    package com.lm.state;
    public class NoRaffleState extends State {
    RaffleActivity activity;
    public NoRaffleState(RaffleActivity activity) {
    this.activity = activity;
    }
    @Override
    public void deduceMoney() {
    System.out.println("扣除50积分成功,您可以抽奖了");
    activity.setState(activity.getCanRaffleState());
    }
    @Override
    public boolean raffle() {
    System.out.println("扣了积分才能抽奖喔!");
    return false;
    }
    @Override
    public void dispensePrize() {
    System.out.println("不能发放奖品");
    }
    }
    package com.lm.state;
    public class CanRaffleState extends State {
    RaffleActivity activity;
    public CanRaffleState(RaffleActivity activity) {
    this.activity = activity;
    }
    @Override
    public void deduceMoney() {
    System.out.println("已经扣取过了积分");
    }
    @Override
    public boolean raffle() {
    System.out.println("正在抽奖,请稍等!");
    Random r = new Random();
    int num = r.nextInt(10);
    if (num == 0) {
    activity.setState(activity.getDispenseState());
    return true;
    } else {
    System.out.println("很遗憾没有抽中奖品!");
    activity.setState(activity.getNoRaffleState());
    return false;
    }
    }
    @Override
    public void dispensePrize() {
    System.out.println("没中奖,不能发放奖品");
    }
    }

    抽奖活动类

    package com.lm.state;
    public class RaffleActivity {
    private State state;
    private int count;
    NoRaffleState noRaffleState = new NoRaffleState(this);
    CanRaffleState canRaffleState = new CanRaffleState(this);
    DispenseState dispenseState = new DispenseState(this);
    DispenseOutState dispenseOutState = new DispenseOutState(this);
    public RaffleActivity(int count) {
    state = getNoRaffleState();
    this.count = count;
    }
    public void deduceMoney() {
    state.deduceMoney();
    }
    public void raffle() {
    if (state.raffle()) {
    state.dispensePrize();
    }
    }
    public State getState() {
    return state;
    }
    public void setState(State state) {
    this.state = state;
    }
    public int getCount() {
    int curCount = count;
    count--;
    return curCount;
    }
    public void setCount(int count) {
    this.count = count;
    }
    public NoRaffleState getNoRaffleState() {
    return noRaffleState;
    }
    public void setNoRaffleState(NoRaffleState noRaffleState) {
    this.noRaffleState = noRaffleState;
    }
    public CanRaffleState getCanRaffleState() {
    return canRaffleState;
    }
    public void setCanRaffleState(CanRaffleState canRaffleState) {
    this.canRaffleState = canRaffleState;
    }
    public DispenseState getDispenseState() {
    return dispenseState;
    }
    public void setDispenseState(DispenseState dispenseState) {
    this.dispenseState = dispenseState;
    }
    public DispenseOutState getDispenseOutState() {
    return dispenseOutState;
    }
    public void setDispenseOutState(DispenseOutState dispenseOutState) {
    this.dispenseOutState = dispenseOutState;
    }
    }

    测试案例

    package com.lm.state;
    public class Client {
    public static void main(String[] args) {
    RaffleActivity activity = new RaffleActivity(1);
    for (int i = 0; i < 30; i++) {
    System.out.println("--------第 " + (i + 1) + " 次抽奖--------");
    activity.deduceMoney();
    activity.raffle();
    }
    }
    }

    借贷平台订单状态管理

    状态模式在借贷平台中的应用

    借贷平台的订单管理涉及多个状态转换,如审核、发布、抢单等。状态模式可以有效地管理这些状态转换,提高代码的可读性和维护性。

    状态转换流程图

    +------------+    +----------------+
    | | | |
    | | --> | |
    +------------+ +----------------+
    | |
    v v
    +------------+ +----------------+
    | | | |
    | | <-- |审核通过 |
    +------------+ +----------------+
    | |
    v v
    +------------+ +----------------+
    | | | |
    | | --> |发布 |
    +------------+ +----------------+
    | |
    v v
    +------------+ +----------------+
    | | | |
    | | <-- |已发布 |
    +------------+ +----------------+

    事件状态关系表

    | 事件 | 状态转换 | 备注 |
    |------|----------|------|
    | 审核 | 通过 | 修改为已审核状态 |
    | 审核 | 未通过 | 修改为已拒绝状态 |
    | 发布 | | 将订单状态改为已发布 |
    | 接单 | | 将订单状态改为已接单 |
    | 失效 | | 将订单状态改为已失效 |
    |付款 | | 将订单状态改为已付款 |
    | 失败 | | 将订单状态改为已失败 |
    | 反馈 | | 将订单状态改为已反馈 |

    状态模式的注意事项

  • 可读性

    状态模式将每个状态的行为封装到对应的类中,代码结构清晰,便于维护和理解。

  • 可扩展性

    状态模式支持轻松添加新的状态,减少了大量的 if-else 判断,提高了代码的可维护性。

  • 开闭原则

    状态模式符合开闭原则,便于新增状态或修改现有状态的行为。

  • 适用性

    适用于状态多且互相转换的场景,特别是在需要动态管理对象行为的系统中。

  • 潜在问题

    状态模式会增加类的数量,管理大量状态时可能导致代码复杂化。

  • 转载地址:http://eugiz.baihongyu.com/

    你可能感兴趣的文章
    现代前端开发框架对比:React、Vue 和 Svelte 的选择指南
    查看>>
    程序员都看不懂的代码
    查看>>
    LLM+多智能体协作:基于CrewAI与DeepSeek的邮件自动化实践
    查看>>
    404错误页面简约清新源码 非常好看
    查看>>
    404页面自动跳转源码
    查看>>
    458. 可怜的小猪
    查看>>
    46:把数字翻译成字符串(动态规划)
    查看>>
    47:礼物的最大值(动态规划)
    查看>>
    49天精通Java,第28天,Java lambda表达式
    查看>>
    49天精通Java,第42天,java stream流详解,从集合遍历,看stream流操作
    查看>>
    500套精美Logo样机模板可直接套用、轻松制作炫酷logo
    查看>>
    centos7上安装 mysql
    查看>>
    5小时内使用DeepSeek写出一篇优质论文的三步攻略指南
    查看>>
    60天新媒体公众号写作秘诀
    查看>>
    C#多线程编程系列(五)- 使用任务并行库
    查看>>
    ASP.NET MVC4 json序列化器
    查看>>
    Android 版本更新之打开apk文件的前生今世
    查看>>
    6410_Linux系统系统移植 和 驱动加载
    查看>>
    64位WIN7+oracle11g+plsql安装
    查看>>
    6天掌握mysql基础视频教程
    查看>>