一、状态模式
1、案例
1.1 APP抽奖活动问题
编写程序完成APP抽奖活动,具体要求如下:
(1)加入每参加一次这个活动要扣除用户50积分,中奖概率是10%
(2)奖品数量固定,抽完就不能抽奖
(3)活动有4个状态:可以抽奖、不能抽奖、发放奖品和奖品领完
2、状态模式基本介绍
2.1 基本介绍
(1)状态模式(State Pattern):它主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态和行为是一一对应的,状态之间可以相互转换。
(2)当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。
2.2 原理类图
- Context类为环境角色,用于维护State实例,这个实例定义当前状态
- State是抽象状态角色,定义一个接口,封装与Context的一个特定接口相关行为
- ConcreteState具体的状态角色,每个子类实现一个与Context的一个状态相关行为
3、状态模式解决APP抽奖问题
3.1 实例类图
Activity类包含所有的状态对象,各个状态子类也含有Activity对象
3.2 代码
3.2.1 State抽象类
1 | // 这是一个抽象类,也可以是一个接口 |
3.2.2 RaffleActivity类
该类和 四种状态类 相互内聚
1 | public class RaffleActivity { |
3.2.3 NoRaffleState类
不能抽奖
1 | // 不能抽奖的状态 |
3.2.4 CanRaffleState类
可以抽奖的状态
1 | import java.util.Random; |
3.2.5 DispenseState类
发放奖品类
1 | // 发放奖品的状态 |
3.2.6 DispenseOutState类
奖品发放完毕
1 | // 奖品发放完毕 |
3.2.7 Client类
1 | public class Client { |
结果:
4、状态模式的注意事项和细节
- 代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中
- 方便维护。将容易产生问题的if-else语句删除了,如果把每个状态的行为都放到一个类中,每次调用方法时都要判断当前是什么状态,不但会产生非常多的if-else语句,而且容易出错
- 符合开闭原则。容易增删状态
- 会产生很多类。每个状态都要一个对应的类,当状态过多时,会产生很多类,加大维护难度
- 应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候,可以考虑使用状态模式