一、状态模式简介
        首先了解一下基本的概念!
1.什么是状态模式
       状态模式(State Pattern),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
2.状态模式是用来解决什么问题的?是用来干什么的?
       状态模式主要解决的是当控制一个对象状态装换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类中,可以把复杂的判断逻辑简单化。
       当一个对象行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。
3.状态模式的结构
Context类:维护一个ConcreteState子类的一个实例,这个实例定义当前的状态。
State类:抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。
ConcreteStateA,ConcreteStateB,ConcreteStateC类:具体状态类,每一个子类实现一个与Context的一个状态相关的行为。
       看完这些概念之后,其实我对状态模式还是很模糊,不知道你们呢?不过通过下面的例子,我们就能很好的理解状态模式了~!
 
 
二、Demo
       我们通过实现投篮机的代码来理解状态模式!
       首先我们来看下,投篮机的状态图:
       从上面我们可以知道,投篮机一共有三个状态(已投币,计分中,未投币),有三个动作(退币,投币,按下开始按钮),其中每个状态下都有可能发生这三个动作,就比如在未投币的状态中,你都可以选择投币,退币和按下开始按钮的动作!好了,分析完之后,我们可以用三个常两来表示三种状态,用三个方法来实现这三个动作!具体看代码:
  1. package com.liangdianshui;
  2. /**
  3. * 投篮机1
  4. *
  5. * @author liangdianshui
  6. *
  7. */
  8. public class ShootingMachine {
  9. // 投篮机有三个状态(已投币,未投币,计分中),分别用三个常量来表示
  10. private final static int HAS_COIN = 0;
  11. private final static int NO_COIN = 1;
  12. private final static int SCORING = 2;
  13. private int mCurrentStatus = NO_COIN;
  14. /**
  15. * 初始化的时候,设置投篮机的状态为未投币的状态
  16. */
  17. public ShootingMachine() {
  18. mCurrentStatus = NO_COIN;
  19. }
  20. /**
  21. * 投币的动作(方法) 玩家在上面的三种状态中都有可能投币
  22. */
  23. public void insertCoin() {
  24. switch (mCurrentStatus) {
  25. case HAS_COIN:
  26. System.out.println("已有硬币,不需要重复投币");
  27. break;
  28. case NO_COIN:
  29. mCurrentStatus = HAS_COIN;
  30. System.out.println("投币成功");
  31. break;
  32. case SCORING:
  33. System.out.println("游戏正在开始,请稍后投币");
  34. break;
  35. }
  36. }
  37. /**
  38. * 退币的动作(方法) 玩家在上面的三种状态中都有可能退币
  39. */
  40. public void backtCoin() {
  41. switch (mCurrentStatus) {
  42. case HAS_COIN:
  43. mCurrentStatus = NO_COIN;
  44. System.out.println("退币成功");
  45. break;
  46. case NO_COIN:
  47. System.out.println("未投入硬币");
  48. break;
  49. case SCORING:
  50. System.out.println("游戏正在进行,不能退币");
  51. break;
  52. }
  53. }
  54. /**
  55. * 按下开始按钮的动作(方法) 玩家在上面的三种状态中都有可能按下开始的按钮
  56. */
  57. public void startScoring() {
  58. switch (mCurrentStatus) {
  59. case HAS_COIN:
  60. mCurrentStatus = SCORING;
  61. System.out.println("游戏开始进行");
  62. scoring();
  63. break;
  64. case NO_COIN:
  65. System.out.println("请投币");
  66. break;
  67. case SCORING:
  68. System.out.println("游戏正在进行");
  69. break;
  70. }
  71. }
  72. /**
  73. * 投篮机计分中
  74. */
  75. public void scoring() {
  76. try {
  77. Thread.sleep(1000); // 模拟时间
  78. System.out.println("时间到,游戏结束");
  79. } catch (InterruptedException e) {
  80. e.printStackTrace();
  81. }
  82. mCurrentStatus = NO_COIN;
  83. }
  84. }

测试类代码:

  1. package com.liangdianshui;
  2. public class Test {
  3. public static void main(String[] args) {
  4. ShootingMachine machine = new ShootingMachine();
  5. System.out.println("----------投币退币---------");
  6. machine.insertCoin();
  7. machine.backtCoin();
  8. System.out.println("----------投币计分---------");
  9. machine.insertCoin();
  10. machine.startScoring();
  11. System.out.println("----------压力测试---------");
  12. machine.insertCoin();
  13. machine.insertCoin();
  14. machine.backtCoin();
  15. machine.backtCoin();
  16. machine.backtCoin();
  17. machine.startScoring();
  18. machine.startScoring();
  19. machine.backtCoin();
  20. }
  21. }

实现的效果:

          好了,感觉写得不错!可是如果需要增加一个奖励,比如投篮投进多少分,给他们出个奖品卷,那么投篮机就多了一个出奖品卷的状态了,按照上面的代码,我们需要在每个动作方法中的判断语句(switch)中增加出奖品卷的状态,如果加一个状态还好,如果很多个,修改起来就很部方便了,而且很容易出错!那么我们可以这样写,写一个状态类,封装好每个状态的方法,然后再让每个状态去实现这些方法,这样修改就比较方便了!
       看下增加出奖品卷的状态的状态图:
状态的接口:
  1. package com.liangdianshui;
  2. public interface State {
  3. // 投币
  4. public void insertCoin();
  5. // 退币
  6. public void backtCoin();
  7. // 按下开始按钮
  8. public void startScoring();
  9. // 投篮机计分中
  10. public void scoring();
  11. // 出奖品卷
  12. public void putPrizeRoll();
  13. }

每个状态的实现类:

  1. package com.liangdianshui;
  2. /**
  3. * 有投币的状态
  4. *
  5. * @author liangdianshui
  6. *
  7. */
  8. public class HasCoinState implements State {
  9. private ShootingMachine mShootingMachine;
  10. public HasCoinState(ShootingMachine shootingMachine) {
  11. this.mShootingMachine = shootingMachine;
  12. }
  13. @Override
  14. public void insertCoin() {
  15. // TODO Auto-generated method stub
  16. System.out.println("已有硬币,不需要重复投币");
  17. }
  18. @Override
  19. public void backtCoin() {
  20. // TODO Auto-generated method stub
  21. System.out.println("退币成功");
  22. mShootingMachine.setState(mShootingMachine.getNoCoinState());
  23. }
  24. @Override
  25. public void startScoring() {
  26. // TODO Auto-generated method stub
  27. System.out.println("游戏开始进行");
  28. mShootingMachine.setState(mShootingMachine.getScoringState());
  29. mShootingMachine.scoring();
  30. }
  31. @Override
  32. public void scoring() {
  33. // TODO Auto-generated method stub
  34. }
  35. @Override
  36. public void putPrizeRoll() {
  37. // TODO Auto-generated method stub
  38. }
  39. }
  1. package com.liangdianshui;
  2. /**
  3. * 未投币的状态
  4. *
  5. * @author liangdianshui
  6. *
  7. */
  8. public class NoCoinState implements State {
  9. private ShootingMachine mShootingMachine;
  10. public NoCoinState(ShootingMachine shootingMachine) {
  11. this.mShootingMachine = shootingMachine;
  12. }
  13. @Override
  14. public void insertCoin() {
  15. // TODO Auto-generated method stub
  16. System.out.println("投币成功");
  17. mShootingMachine.setState(mShootingMachine.getHasCoinState());
  18. }
  19. @Override
  20. public void backtCoin() {
  21. // TODO Auto-generated method stub
  22. System.out.println("未投入硬币");
  23. }
  24. @Override
  25. public void startScoring() {
  26. // TODO Auto-generated method stub
  27. System.out.println("请投币");
  28. }
  29. @Override
  30. public void scoring() {
  31. // TODO Auto-generated method stub
  32. }
  33. @Override
  34. public void putPrizeRoll() {
  35. // TODO Auto-generated method stub
  36. }
  37. }
  1. package com.liangdianshui;
  2. /**
  3. * 出奖品卷的状态
  4. *
  5. * @author liangdianshui
  6. *
  7. */
  8. public class PutPrizeRollState implements State {
  9. private ShootingMachine mShootingMachine;
  10. public PutPrizeRollState(ShootingMachine shootingMachine) {
  11. this.mShootingMachine = shootingMachine;
  12. }
  13. @Override
  14. public void insertCoin() {
  15. // TODO Auto-generated method stub
  16. System.out.println("正在出奖品卷,请稍后投币");
  17. }
  18. @Override
  19. public void backtCoin() {
  20. // TODO Auto-generated method stub
  21. System.out.println("正在出奖品卷,不能退币");
  22. }
  23. @Override
  24. public void startScoring() {
  25. // TODO Auto-generated method stub
  26. System.out.println("正在出奖品卷,不能开始游戏");
  27. }
  28. @Override
  29. public void scoring() {
  30. // TODO Auto-generated method stub
  31. }
  32. @Override
  33. public void putPrizeRoll() {
  34. // TODO Auto-generated method stub
  35. try {
  36. Thread.sleep(1000); // 模拟出奖品卷
  37. System.out.println("出奖品卷完成");
  38. mShootingMachine.setState(mShootingMachine.getNoCoinState());
  39. } catch (InterruptedException e) {
  40. // TODO Auto-generated catch block
  41. e.printStackTrace();
  42. }
  43. }
  44. }
  1. package com.liangdianshui;
  2. import java.util.Random;
  3. /**
  4. * 计分中的状态
  5. *
  6. * @author liangdianshui
  7. *
  8. */
  9. public class ScoringState implements State {
  10. private ShootingMachine mShootingMachine;
  11. private Random random = new Random();
  12. public ScoringState(ShootingMachine shootingMachine) {
  13. this.mShootingMachine = shootingMachine;
  14. }
  15. @Override
  16. public void insertCoin() {
  17. // TODO Auto-generated method stub
  18. System.out.println("游戏正在开始,请稍后投币");
  19. }
  20. @Override
  21. public void backtCoin() {
  22. // TODO Auto-generated method stub
  23. System.out.println("游戏正在进行,不能退币");
  24. }
  25. @Override
  26. public void startScoring() {
  27. // TODO Auto-generated method stub
  28. System.out.println("游戏正在进行");
  29. scoring();
  30. }
  31. @Override
  32. public void scoring() {
  33. // TODO Auto-generated method stub
  34. int randNum = random.nextInt(80) + 15; // 随机生成15到94的一个随机数,代表游戏的分数
  35. try {
  36. Thread.sleep(1000); // 模拟时间
  37. if (randNum > 50) {
  38. System.out.println("时间到,您的分数是:" + randNum + ",恭喜你获取到奖品卷");
  39. mShootingMachine.setState(mShootingMachine.getPutPrizeRollState());
  40. mShootingMachine.putPrizeRollState();
  41. } else {
  42. System.out.println("时间到,您的分数是:" + randNum + ",游戏结束");
  43. }
  44. } catch (InterruptedException e) {
  45. e.printStackTrace();
  46. }
  47. }
  48. @Override
  49. public void putPrizeRoll() {
  50. // TODO Auto-generated method stub
  51. }
  52. }

然后写个投篮机的实现类:

  1. package com.liangdianshui;
  2. /**
  3. * 投篮机2
  4. *
  5. * @author liangdianshui
  6. *
  7. */
  8. public class ShootingMachine {
  9. private State hasCoinState;
  10. private State noCoinState;
  11. private State putPrizeRollState;
  12. private State scoringState;
  13. private State mCurrentStatus = noCoinState;
  14. public ShootingMachine() {
  15. hasCoinState = new HasCoinState(this);
  16. noCoinState = new NoCoinState(this);
  17. putPrizeRollState = new PutPrizeRollState(this);
  18. scoringState = new ScoringState(this);
  19. mCurrentStatus = noCoinState;
  20. }
  21. /**
  22. * 设置投篮机的状态
  23. */
  24. public void setState(State state) {
  25. this.mCurrentStatus = state;
  26. }
  27. // 投币
  28. public void insertCoin() {
  29. mCurrentStatus.insertCoin();
  30. }
  31. // 退币
  32. public void backtCoin() {
  33. mCurrentStatus.backtCoin();
  34. }
  35. // 按下开始游戏的按钮
  36. public void startScoring() {
  37. mCurrentStatus.startScoring();
  38. }
  39. // 投篮机计分中
  40. public void scoring() {
  41. mCurrentStatus.scoring();
  42. }
  43. // 出奖品卷
  44. public void putPrizeRollState() {
  45. mCurrentStatus.putPrizeRoll();
  46. }
  47. public State getHasCoinState() {
  48. return hasCoinState;
  49. }
  50. public void setHasCoinState(State hasCoinState) {
  51. this.hasCoinState = hasCoinState;
  52. }
  53. public State getNoCoinState() {
  54. return noCoinState;
  55. }
  56. public void setNoCoinState(State noCoinState) {
  57. this.noCoinState = noCoinState;
  58. }
  59. public State getPutPrizeRollState() {
  60. return putPrizeRollState;
  61. }
  62. public void setPutPrizeRollState(State putPrizeRollState) {
  63. this.putPrizeRollState = putPrizeRollState;
  64. }
  65. public State getScoringState() {
  66. return scoringState;
  67. }
  68. public void setScoringState(State scoringState) {
  69. this.scoringState = scoringState;
  70. }
  71. }

测试类:

  1. package com.liangdianshui;
  2. public class Test {
  3. public static void main(String[] args) {
  4. ShootingMachine machine = new ShootingMachine();
  5. System.out.println("----------投币退币---------");
  6. machine.insertCoin();
  7. machine.backtCoin();
  8. System.out.println("----------投币,开始投篮1---------");
  9. machine.insertCoin();
  10. machine.startScoring();
  11. System.out.println("----------投币,开始投篮2---------");
  12. machine.insertCoin();
  13. machine.startScoring();
  14. System.out.println("----------投币,开始投篮3---------");
  15. machine.insertCoin();
  16. machine.startScoring();
  17. System.out.println("----------压力测试---------");
  18. machine.insertCoin();
  19. machine.insertCoin();
  20. machine.backtCoin();
  21. machine.backtCoin();
  22. machine.backtCoin();
  23. machine.startScoring();
  24. machine.startScoring();
  25. machine.backtCoin();
  26. }
  27. }

最后来看下运行的结果:

Android开源项目SlidingMenu深切解析的更多相关文章

  1. Android 开源项目源码解析(第二期)

    Android 开源项目源码解析(第二期) 阅读目录 android-Ultra-Pull-To-Refresh 源码解析 DynamicLoadApk 源码解析 NineOldAnimations ...

  2. Android开源项目SlidingMenu本学习笔记(两)

    我们已经出台SlidingMenu使用:Android开源项目SlidingMenu本学习笔记(一个),接下来再深入学习下.依据滑出项的Menu切换到相应的页面 文件夹结构: watermark/2/ ...

  3. Android开源项目SlidingMenu学习(二)

    前一篇SlidingMenu学习(一)文章中了解了导入SlidingMenu到我们项目经常出现的问题,下面我们正式学习. 先看一个效果: 看到两幅图片的差别了吗,左边的一栏时可以滑动的,可以隐藏掉,现 ...

  4. Android开源项目SlidingMenu深入剖析

    SlidingMenu简介: SlidingMenu的是一种比较新的设置界面或配置界面效果,在主界面左滑或者右滑出现设置界面,能方便的进行各种操作.目前有大量的应用都在使用这一效果.如Evernote ...

  5. Android开源项目SlidingMenu的学习笔记(一)

    SlidingMenu是眼下在应用程序上非常流行的一种UI技术.能够实现一种比較炫的滑动效果,SlidingMenu是Git上托管的一个项目,开源免费的.SlidingMenu作为一个Library的 ...

  6. [原创]android开源项目源码解析(一)----CircleImageView的源码解析

    CircleImageView的代码很简洁,因此先将此工程作为源码解析系列的第一篇文章. 解析说明都在代码里了. /* * Copyright 2014 - 2015 Henning Dodenhof ...

  7. Android 开源项目及其学习

    Android 系统研究:http://blog.csdn.net/luoshengyang/article/details/8923485 Android 腾讯技术人员博客 http://hukai ...

  8. 【Android UI设计与开发】9:滑动菜单栏(一)开源项目SlidingMenu的使用和示例

    一.SlidingMenu简介 相信大家对SlidingMenu都不陌生了,它是一种比较新的设置界面或配置界面的效果,在主界面左滑或者右滑出现设置界面效果,能方便的进行各种操作.很多优秀的应用都采用了 ...

  9. 【Android UI设计与开发】第17期:滑动菜单栏(二)开源项目SlidingMenu的示例

    通过上一篇文章的讲解,相信大家对于开源项目SlidingMenu都有了一个比较初步的了解(不了解的可以参考上 一篇文章),那么从这一章开始,博主将会以SlidingMenu为重心,给大家带来非常丰富的 ...

随机推荐

  1. 暑假集训单切赛第一场 CF 191A Dynasty Puzzles

    题意不说了,看原题吧,思路见代码: #include <iostream> #include <stdio.h> #include <string.h> #incl ...

  2. 关于dynamic_cast

    http://www.groad.net/bbs/read.php?tid-5476.html dynamic_cast 进行运行时强制转换.如果在执行时转换非法,则会转换失败.dynamic_cas ...

  3. stringgird中使用TClientDataSet排序的问题

    function TfrmMain.createIIReport(cdsBody: TClientDataSet;  silent: Boolean): String;var    s,sText: ...

  4. ibatis框架的sqlmapclient接口

    SqlMapClient,是iBatis中的重要接口,这个接口涉及到对SQL映射的执行和批处理. 现在,就先了解它的对query开头方法的定义. 首先是 queryForList 方法: //指定SQ ...

  5. 搜索之BM25和BM25F模型

    www.netfoucs.com/article/wdxin1322/94603.html#

  6. GuessNum

    import java.util.Scanner;import java.util.Random;/***猜数字,使用随机一个0-100的数字,然后用户猜,猜中了就提示猜中了,*否则提示猜大了还是猜小 ...

  7. Apollo,Python,Delphi与Oracle之间的神话关系

    在希腊历史上Delphi曾被认为是世界的中心,Apollo杀死Python后将其据为己有,在其神庙上刻有Oracle,曰:Γνωθι δεαυτόν (认识你自己自身关怀,Cognosce te ip ...

  8. 修改linux终端命令行颜色

    进入修改:vim /root/.bashrc 1.PS1 要修改linux终端命令行颜色,我们需要用到PS1,PS1是Linux终端用户的一个环境变量,用来说明命令行提示符的设置.在终端输入命令:#s ...

  9. Android Handler值传递(文)

    发送消息: public static class TimeReceiver extends BroadcastReceiver { @Override public void onReceive(C ...

  10. java 日期格式转换EEE MMM dd HH:mm:ss z yyyy

    SimpleDateFormat parserSDF = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzzz yyyy", Locale. ...