一、状态模式简介
        首先了解一下基本的概念!
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. C# 面向对象之概念理解(3)

    多态 多态是指两个或多个属于不同类的对象,对同一个消息(方法调用)做出不同响应的能力. 多态(<韦氏大词典>)中定义:可以呈现不同形式的能力或状态. C#如何实现多态的知识——即继承上覆载 ...

  2. Sina App Engine(SAE)入门教程(5)- SaeSegment(中文分词服务)使用

    分词能干什么? 提取一篇文章的关键字 检测特定的段落中有没有违禁词 智能机器人 …..尽你所想 开启SAE 分词服务 首先你需要在sae的管理面板开始分词服务后才能使用sae的服务.具体的开启操作: ...

  3. VirtualUI - Convert your Windows App to HTML5

    http://www.cybelesoft.com/thinfinity/virtualui/

  4. tomcat version

    Tomcat version 6.0 only supports J2EE 1.2, 1.3, 1.4, and Java EE 5 Web modules   转自:http://jingwang0 ...

  5. Axel linux下多线程下载工具

    Axel 是 Linux 下一个不错的HTTP/FTP高速下载工具.支持多线程下载.断点续传,且可以从多个地址或者从一个地址的多个连接来下载同一个文件.适合网速不给力时多线程下载提高下载速度.比如在国 ...

  6. renameTo()方法的用法

    使用renameTo()方法,可以将文件data.txt从C:\JavaApp\IOTest1\目录移动到C:\目录,并改名为newdata.txt import java.io.File; //将文 ...

  7. Maven那点事儿(Eclipse版)

    Maven那点事儿(Eclipse版)   前言: 由于最近工作学习,总是能碰到Maven的源码.虽然平时工作并不使用Maven,但是为了学习一些源码,还是必须要了解下.这篇文章不是一个全面的Mave ...

  8. C# 使用AutoResetEvent进行线程同步

    AutoResetEvent 允许线程通过发信号互相通信. 通常,当线程需要独占访问资源时使用该类. 线程通过调用 AutoResetEvent 上的 WaitOne 来等待信号. 如果 AutoRe ...

  9. MapReduce编程系列 — 5:单表关联

    1.项目名称: 2.项目数据: chile    parentTom    LucyTom    JackJone    LucyJone    JackLucy    MaryLucy    Ben ...

  10. SQL 分组排序分页(大神帮写的膜拜一下)

    查询全部: SELECT P3.ID, P3.Name, P3.AddTimeFROM (SELECT Name, MAX(AddTime) AS MaxAddTime FROM Product AS ...