笔记 笔记
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

EasT-Duan

Java 开发
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

购买兑换码请添加

添加时候请写好备注,否则无法通过。

  • 设计模式

    • 简介

    • 原则

    • UML

    • 创建型

    • 结构型

    • 行为型

      • 模板模式
      • 命令模式
      • 访问者模式
      • 迭代器模式
      • 中介者模式
      • 备忘录模式
      • 解释器模式
      • 状态模式
        • 简介
        • 代码示例
        • 说明
      • 策略模式
      • 职责链模式
  • JVM 详解

  • Linux

  • Redis

  • 分布式锁

  • Shiro

  • Gradle

  • Java 进阶
  • 设计模式
  • 行为型
EasT-Duan
2023-12-04
目录

状态模式

欢迎来到我的 ChatGPT 中转站,极具性价比,为付费不方便的朋友提供便利,有需求的可以添加左侧 QQ 二维码,另外,邀请新用户能获取余额哦!最后说一句,那啥:请自觉遵守《生成式人工智能服务管理暂行办法》。

# 简介

状态模式(State Pattern):它主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态和行为是一一对应的,状态之间可以相互转换。

当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。

  • Context 类为环境角色,用于维护 State 实例,这个实例定义当前状态。
  • State 是抽象状态角色,定义一个接口封装与 Context 的一个特点接口相关行为。
  • ConcreteState 具体的状态角色,每个子类实现一个与 Context 的一个状态相关行为。

# 代码示例

例如:用户扣积分抽奖,用户每次抽奖扣除 50 积分,如果账户积分大于 50 则可以抽奖,如果小于就不能抽奖,如果中奖就发放奖品,如果奖品发放完毕则无法领取。

/**
 * 状态接口
 */
public interface State {
    /**
     * 扣除积分
     */
    void deductPoints(int points);

    /**
     * 是否抽中奖品
     */
    boolean raffle();

    /**
     * 发放奖品
     */
    void dispensePrize();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
 * 不能抽奖的状态
 */
@AllArgsConstructor
public class NoRaffleState implements State {
    private final RaffleActivity activity;

    // 扣除积分,然后把状态设置为可以抽奖
    @Override
    public void deductPoints(int currentPoints) {
        if (currentPoints >= 50) {
            System.out.println("积分充足,您可以抽奖了");
            activity.setState(activity.getCanRaffleState());
        } else {
            System.out.println("积分不足,不能抽奖");
        }
    }

    // 在当前状态下不能抽奖
    @Override
    public boolean raffle() {
        System.out.println("扣了积分才能抽奖!");
        return false;
    }

    // 在当前状态下不会发放奖品
    @Override
    public void dispensePrize() {
        System.out.println("没有奖品发放!");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 * 发放奖品的状态
 */
@AllArgsConstructor
public class DispenseState implements State {
    private final RaffleActivity activity;

    /**
     * 扣除积分
     */
    @Override
    public void deductPoints(int points) {
        System.out.println("不能扣除积分!");
    }

    /**
     * 是否抽中奖品
     */
    @Override
    public boolean raffle() {
        System.out.println("不能抽奖!");
        return false;
    }

    /**
     * 发放奖品 如果奖品还有剩余,则将状态设置为不能抽奖,否则设置为奖品领完
     */
    @Override
    public void dispensePrize() {
        if (activity.getCount() > 0) {
            System.out.println("恭喜中奖!");
            activity.setState(activity.getNoRaffleState());
        } else {
            System.out.println("很遗憾,奖品发送完了!");
            activity.setState(activity.getDispenseOutState());
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
 * 奖品发放完毕状态 说明,当我们activity 改变成 DispenseOutState, 抽奖活动结束
 */
@AllArgsConstructor
public class DispenseOutState implements State {
    private final RaffleActivity activity;

    // 在当前状态下不能扣除积分
    @Override
    public void deductPoints(int points) {

        System.out.println("奖品发送完了,不能再扣除积分了!");
    }

    // 在当前状态下不能抽奖
    @Override
    public boolean raffle() {
        System.out.println("奖品发送完了,不能再抽奖了!");
        return false;
    }

    // 在当前状态下不能发放奖品
    @Override
    public void dispensePrize() {
        System.out.println("奖品发送完了,不能再发放奖品了!");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
 * 可以抽奖的状态
 */
@AllArgsConstructor
public class CanRaffleState implements State {
    private final RaffleActivity activity;

    /**
     *  扣除积分,然后把状态设置为不能抽奖
     */
    @Override
    public void deductPoints(int currentPoints) {
        if (currentPoints >= 50) {
            System.out.println("扣除50积分,您可以继续抽奖");
            activity.setPoints(currentPoints - 50);
            // 切换状态
            activity.setState(activity.getCanRaffleState());
        } else {
            System.out.println("积分不足,不能抽奖");
            activity.setState(activity.getNoRaffleState());
        }
    }

    /**
     * 是否抽中奖品
     */
    @Override
    public boolean raffle() {
        System.out.println("正在抽奖,请稍等!");
        int random = (int) (Math.random() * 10);
        if (random == 0) {
            activity.setState(activity.getDispenseState());
            return true;
        } else {
            System.out.println("很遗憾,您没有中奖!");
            activity.setState(activity.getNoRaffleState());
            return false;
        }
    }

    /**
     * 发放奖品
     */
    @Override
    public void dispensePrize() {
        System.out.println("没有奖品发放!");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
 * 切换状态
 */
public class RaffleActivity {

    @Setter
    private State state;
    private int count; //奖品数量
    @Getter
    @Setter
    private int points;// 积分
    @Getter
    private State noRaffleState = new NoRaffleState(this);
    @Getter
    private State canRaffleState = new CanRaffleState(this);
    @Getter
    private State dispenseState = new DispenseState(this);
    @Getter
    private State dispenseOutState = new DispenseOutState(this);

    public RaffleActivity(int count, int points) {
        this.state = getNoRaffleState();
        this.count = count;
        this.points = points;
    }

    //扣除积分
    public void deductPoints() {
        if (points >= 50) {
            state.deductPoints(points);
        } else {
            System.out.println("积分不足,不能抽奖");
            state = getNoRaffleState();
        }
    }

    public void raffle() {
        // 如果当前的状态是抽奖成功
        if (state.raffle()) {
            //领取奖品
            state.dispensePrize();
        }
    }

    // 领取奖品
    public int getCount() {
        int curCount = count;
        count--;
        return curCount;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

# 说明

  1. 代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中。
  2. 方便维护。将容易产生问题的 if-else 语句删除了,如果把每个状态的行为都放到一个类中,每次调用方法时都要判断当前是什么状态,不但会产出很多 if-else 语句,而且容易出错。
  3. 符合 “开闭原则”。容易增删状态。

但是会产生很多类。每个状态都要一个对应的类,当状态过多时会产生很多类,加大维护难度。

应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候,可以考虑使用状态模式。

#设计模式
上次更新: 2025/04/12, 05:37:39
解释器模式
策略模式

← 解释器模式 策略模式→

最近更新
01
Reactor 核心
02-24
02
前置条件
10-30
03
计算机网络
09-13
更多文章>
Theme by Vdoing | Copyright © 2019-2025 powered by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式