状态模式
基本介绍
1.状态模式:他主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态和行为是一一对应的,状态之间可以相互转换。
2.当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类。
对原理类图的说明-即(状态模式的角色及职责)
1.Context 类为环境角色,用于维护State实例,这个实例定义当前状态
2.State 是抽象状态角色,定义一个接口封装与Context 的一个特点接口相关行为
3.ConcreteState 具体的状态角色,每个子类实现一个与Context 的一个状态相关行为。
状态模式解决APP抽奖问题
完成APP抽奖活动项目,使用状态模式
2.思路粉丝和图解(类图)
-定义出一个接口叫状态接口,每个状态都实现它。
-接口有扣除积分方法、抽奖方法、方法奖品方法
3.具体代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package com.state; /** * 状态抽象类 */ public abstract class State { //扣除积分 -50 public abstract void deduceMoney(); //是否抽中奖品 public abstract boolean raffle(); //发放奖品 public abstract void dispensePrise(); } |
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 | package com.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()); } /** * 当前状态不能抽奖 * @return */ @Override public boolean raffle() { System.out.println( "扣了积分才能抽奖哦" ); return false ; } /** * 当前状态不能发放奖品 */ @Override public void dispensePrise() { 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 49 | package com.state; import java.util.Random; /** * 可以抽奖的状态 * * @author Administrator * */ 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 ); // 10%中奖机会 if (num == 0 ) { // 改 变 活 动 状 态 为 发 放 奖 品 context activity.setState(activity.getDispenseState()); return true ; } else { System.out.println( "很遗憾没有抽中奖品!" ); // 改变状态为不能抽奖 activity.setState(activity.getNoRafflleState()); return false ; } } // 不能发放奖品 @Override public void dispensePrise() { 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 | package com.state; /** * 发放奖品的状态 * * @author Administrator * */ public class DispenseState extends State { // 初始化时传入活动引用,发放奖品后改变其状态 RaffleActivity activity; public DispenseState(RaffleActivity activity) { this .activity = activity; } @Override public void deduceMoney() { System.out.println( "不能扣除积分" ); } @Override public boolean raffle() { System.out.println( "不能抽奖" ); return false ; } //发放奖品 @Override public void dispensePrise() { if (activity.getCount() > 0 ) { System.out.println( "恭喜中奖了" ); // 改变状态为不能抽奖 activity.setState(activity.getNoRafflleState()); } else { System.out.println( "很遗憾,奖品发送完了" ); // 改变状态为奖品发送完毕, 后面我们就不可以抽奖 activity.setState(activity.getDispensOutState()); //System.out.println("抽奖活动结束"); //System.exit(0); } } // } |
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 | package com.state; /** * 奖品发放完毕状态 说明,当我们 activity 改变成 DispenseOutState, 抽奖活动结束 * * @author Administrator * */ public class DispenseOutState extends State { // 初始化时传入活动引用 RaffleActivity activity; public DispenseOutState(RaffleActivity activity) { this .activity = activity; } @Override public void deduceMoney() { System.out.println( "奖品发送完了,请下次再参加" ); } @Override public boolean raffle() { System.out.println( "奖品发送完了,请下次再参加" ); return false ; } @Override public void dispensePrise() { 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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | package com.state; /** * 抽奖活动 // * * @author Administrator * */ public class RaffleActivity { // state 表示活动当前的状态,是变化 State state = null ; // 奖品数量 int count = 0 ; // 四个属性,表示四种状态 State noRafflleState = new NoRaffleState( this ); State canRaffleState = new CanRaffleState( this ); State dispenseState = new DispenseState( this ); State dispensOutState = new DispenseOutState( this ); // 构造器 // 1. 初始化当前的状态为 noRafflleState(即不能抽奖的状态) // 2. 初始化奖品的数量 public RaffleActivity( int count) { this .state = getNoRafflleState(); this .count = count; } // 扣分, 调用当前状态的 deductMoney public void debuctMoney() { state.deduceMoney(); } // 抽奖 public void raffle() { // 如果当前的状态是抽奖成功 if (state.raffle()) { // 领取奖品 state.dispensePrise(); } } public State getState() { return state; } public void setState(State state) { this .state = state; } // 这里请大家注意,每领取一次奖品,count-- public int getCount() { int curCount = count; count--; return curCount; } public void setCount( int count) { this .count = count; } public State getNoRafflleState() { return noRafflleState; } public void setNoRafflleState(State noRafflleState) { this .noRafflleState = noRafflleState; } public State getCanRaffleState() { return canRaffleState; } public void setCanRaffleState(State canRaffleState) { this .canRaffleState = canRaffleState; } public State getDispenseState() { return dispenseState; } public void setDispenseState(State dispenseState) { this .dispenseState = dispenseState; } public State getDispensOutState() { return dispensOutState; } public void setDispensOutState(State dispensOutState) { this .dispensOutState = dispensOutState; } } |
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 | package com.state; /** * 状态模式测试类 * * @author Administrator * */ public class Client { public static void main(String[] args) { // 创建活动对象,奖品有 1 个奖品 RaffleActivity activity = new RaffleActivity( 1 ); // 我们连续抽 300 次奖 for ( int i = 0 ; i < 40 ; i++) { System.out.println( "--------第" + (i + 1 ) + "次抽奖----------" ); // 参加抽奖,第一步点击扣除积分 activity.debuctMoney(); // 第二步抽奖 activity.raffle(); } } } |
运行结果:
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 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | --------第 1 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 恭喜中奖了 --------第 2 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 3 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 4 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 5 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 6 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 7 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 8 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 9 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 10 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 11 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 12 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 13 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 14 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 15 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 16 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 17 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾没有抽中奖品! --------第 18 次抽奖---------- 扣除 50 积分成功,您可以抽奖了 正在抽奖,请稍等! 很遗憾,奖品发送完了 --------第 19 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 20 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 21 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 22 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 23 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 24 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 25 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 26 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 27 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 28 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 29 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 30 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 31 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 32 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 33 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 34 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 35 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 36 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 37 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 38 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 39 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 --------第 40 次抽奖---------- 奖品发送完了,请下次再参加 奖品发送完了,请下次再参加 |
1.代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中。
2.方便维护。将容易产生问题的 if-else 语句删除了,如果把每个桩体的行为都放到一个类中,每次调用方法时都要判断当前是什么状态,不但会产生出很多 if-else 语句,而且容易出错。
3.会产生很多类。每个状态都要一个对应的类,当状态过多的时候会产生很多的状态类,加大维护难度。
4.应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状态要求有不同的行为的时候,可以考虑使用状态模式。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY