请编写程序完成APP抽奖活动 具
体要求如下:
1) 假如每参加一次这个活动要扣除用户50积分,中奖概率是10%
2) 奖品数量固定,抽完就不能抽奖
3) 活动有四个状态: 可以抽奖、不能抽奖、发放奖品和奖品领完

image.png

状态模式

状态模式(State Pattern):它主要用来解决对象在多种状态转换时,需要对外输出不同行为的问题。状态和行为是一 一 对应的,状态之间可以互相转换
当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类

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

image.png

  1. /**
  2. * 状态抽象类
  3. * @author Administrator
  4. *
  5. */
  6. public abstract class State {
  7. // 扣除积分 - 50
  8. public abstract void deductMoney();
  9. // 是否抽中奖品
  10. public abstract boolean raffle();
  11. // 发放奖品
  12. public abstract void dispensePrize();
  13. }
  14. /**
  15. * 不能抽奖状态
  16. * @author Administrator
  17. *
  18. */
  19. public class NoRaffleState extends State {
  20. // 初始化时传入活动引用,扣除积分后改变其状态
  21. RaffleActivity activity;
  22. public NoRaffleState(RaffleActivity activity) {
  23. this.activity = activity;
  24. }
  25. // 当前状态可以扣积分 , 扣除后,将状态设置成可以抽奖状态
  26. @Override
  27. public void deductMoney() {
  28. System.out.println("扣除50积分成功,您可以抽奖了");
  29. activity.setState(activity.getCanRaffleState());
  30. }
  31. // 当前状态不能抽奖
  32. @Override
  33. public boolean raffle() {
  34. System.out.println("扣了积分才能抽奖喔!");
  35. return false;
  36. }
  37. // 当前状态不能发奖品
  38. @Override
  39. public void dispensePrize() {
  40. System.out.println("不能发放奖品");
  41. }
  42. }
  43. /**
  44. * 发放奖品的状态
  45. * @author Administrator
  46. *
  47. */
  48. public class DispenseState extends State {
  49. // 初始化时传入活动引用,发放奖品后改变其状态
  50. RaffleActivity activity;
  51. public DispenseState(RaffleActivity activity) {
  52. this.activity = activity;
  53. }
  54. //
  55. @Override
  56. public void deductMoney() {
  57. System.out.println("不能扣除积分");
  58. }
  59. @Override
  60. public boolean raffle() {
  61. System.out.println("不能抽奖");
  62. return false;
  63. }
  64. //发放奖品
  65. @Override
  66. public void dispensePrize() {
  67. if(activity.getCount() > 0){
  68. System.out.println("恭喜中奖了");
  69. // 改变状态为不能抽奖
  70. activity.setState(activity.getNoRafflleState());
  71. }else{
  72. System.out.println("很遗憾,奖品发送完了");
  73. // 改变状态为奖品发送完毕, 后面我们就不可以抽奖
  74. activity.setState(activity.getDispensOutState());
  75. //System.out.println("抽奖活动结束");
  76. //System.exit(0);
  77. }
  78. }
  79. }
  80. /**
  81. * 奖品发放完毕状态
  82. * 说明,当我们activity 改变成 DispenseOutState, 抽奖活动结束
  83. * @author Administrator
  84. *
  85. */
  86. public class DispenseOutState extends State {
  87. // 初始化时传入活动引用
  88. RaffleActivity activity;
  89. public DispenseOutState(RaffleActivity activity) {
  90. this.activity = activity;
  91. }
  92. @Override
  93. public void deductMoney() {
  94. System.out.println("奖品发送完了,请下次再参加");
  95. }
  96. @Override
  97. public boolean raffle() {
  98. System.out.println("奖品发送完了,请下次再参加");
  99. return false;
  100. }
  101. @Override
  102. public void dispensePrize() {
  103. System.out.println("奖品发送完了,请下次再参加");
  104. }
  105. }
  106. /**
  107. * 可以抽奖的状态
  108. * @author Administrator
  109. *
  110. */
  111. public class CanRaffleState extends State {
  112. RaffleActivity activity;
  113. public CanRaffleState(RaffleActivity activity) {
  114. this.activity = activity;
  115. }
  116. //已经扣除了积分,不能再扣
  117. @Override
  118. public void deductMoney() {
  119. System.out.println("已经扣取过了积分");
  120. }
  121. //可以抽奖, 抽完奖后,根据实际情况,改成新的状态
  122. @Override
  123. public boolean raffle() {
  124. System.out.println("正在抽奖,请稍等!");
  125. Random r = new Random();
  126. int num = r.nextInt(10);
  127. // 10%中奖机会
  128. if(num == 0){
  129. // 改变活动状态为发放奖品 context
  130. activity.setState(activity.getDispenseState());
  131. return true;
  132. }else{
  133. System.out.println("很遗憾没有抽中奖品!");
  134. // 改变状态为不能抽奖
  135. activity.setState(activity.getNoRafflleState());
  136. return false;
  137. }
  138. }
  139. // 不能发放奖品
  140. @Override
  141. public void dispensePrize() {
  142. System.out.println("没中奖,不能发放奖品");
  143. }
  144. }
  1. /**
  2. * 抽奖活动 //
  3. *
  4. * @author Administrator
  5. *
  6. */
  7. public class RaffleActivity {
  8. // state 表示活动当前的状态,是变化
  9. State state = null;
  10. // 奖品数量
  11. int count = 0;
  12. // 四个属性,表示四种状态
  13. State noRafflleState = new NoRaffleState(this);
  14. State canRaffleState = new CanRaffleState(this);
  15. State dispenseState = new DispenseState(this);
  16. State dispensOutState = new DispenseOutState(this);
  17. //构造器
  18. //1. 初始化当前的状态为 noRafflleState(即不能抽奖的状态)
  19. //2. 初始化奖品的数量
  20. public RaffleActivity( int count) {
  21. this.state = getNoRafflleState();
  22. this.count = count;
  23. }
  24. //扣分, 调用当前状态的 deductMoney
  25. public void debuctMoney(){
  26. state.deductMoney();
  27. }
  28. //抽奖
  29. public void raffle(){
  30. // 如果当前的状态是抽奖成功
  31. if(state.raffle()){
  32. //领取奖品
  33. state.dispensePrize();
  34. }
  35. }
  36. public State getState() {
  37. return state;
  38. }
  39. public void setState(State state) {
  40. this.state = state;
  41. }
  42. //这里请大家注意,每领取一次奖品,count--
  43. public int getCount() {
  44. int curCount = count;
  45. count--;
  46. return curCount;
  47. }
  48. public void setCount(int count) {
  49. this.count = count;
  50. }
  51. public State getNoRafflleState() {
  52. return noRafflleState;
  53. }
  54. public void setNoRafflleState(State noRafflleState) {
  55. this.noRafflleState = noRafflleState;
  56. }
  57. public State getCanRaffleState() {
  58. return canRaffleState;
  59. }
  60. public void setCanRaffleState(State canRaffleState) {
  61. this.canRaffleState = canRaffleState;
  62. }
  63. public State getDispenseState() {
  64. return dispenseState;
  65. }
  66. public void setDispenseState(State dispenseState) {
  67. this.dispenseState = dispenseState;
  68. }
  69. public State getDispensOutState() {
  70. return dispensOutState;
  71. }
  72. public void setDispensOutState(State dispensOutState) {
  73. this.dispensOutState = dispensOutState;
  74. }
  75. }
  1. public static void main(String[] args) {
  2. // TODO Auto-generated method stub
  3. // 创建活动对象,奖品有1个奖品
  4. RaffleActivity activity = new RaffleActivity(1);
  5. // 我们连续抽300次奖
  6. for (int i = 0; i < 30; i++) {
  7. System.out.println("--------第" + (i + 1) + "次抽奖----------");
  8. // 参加抽奖,第一步点击扣除积分
  9. activity.debuctMoney();
  10. // 第二步抽奖
  11. activity.raffle();
  12. }
  13. }

订单问题 案例

image.png

image.png

image.png

  1. /**
  2. * 状态接口
  3. * @author Administrator
  4. *
  5. */
  6. public interface State {
  7. /**
  8. * 电审
  9. */
  10. void checkEvent(Context context);
  11. /**
  12. * 电审失败
  13. */
  14. void checkFailEvent(Context context);
  15. /**
  16. * 定价发布
  17. */
  18. void makePriceEvent(Context context);
  19. /**
  20. * 接单
  21. */
  22. void acceptOrderEvent(Context context);
  23. /**
  24. * 无人接单失效
  25. */
  26. void notPeopleAcceptEvent(Context context);
  27. /**
  28. * 付款
  29. */
  30. void payOrderEvent(Context context);
  31. /**
  32. * 接单有人支付失效
  33. */
  34. void orderFailureEvent(Context context);
  35. /**
  36. * 反馈
  37. */
  38. void feedBackEvent(Context context);
  39. String getCurrentState();
  40. }
  41. public abstract class AbstractState implements State {
  42. protected static final RuntimeException EXCEPTION = new RuntimeException("操作流程不允许");
  43. //抽象类,默认实现了 State 接口的所有方法
  44. //该类的所有方法,其子类(具体的状态类),可以有选择的进行重写
  45. @Override
  46. public void checkEvent(Context context) {
  47. throw EXCEPTION;
  48. }
  49. @Override
  50. public void checkFailEvent(Context context) {
  51. throw EXCEPTION;
  52. }
  53. @Override
  54. public void makePriceEvent(Context context) {
  55. throw EXCEPTION;
  56. }
  57. @Override
  58. public void acceptOrderEvent(Context context) {
  59. throw EXCEPTION;
  60. }
  61. @Override
  62. public void notPeopleAcceptEvent(Context context) {
  63. throw EXCEPTION;
  64. }
  65. @Override
  66. public void payOrderEvent(Context context) {
  67. throw EXCEPTION;
  68. }
  69. @Override
  70. public void orderFailureEvent(Context context) {
  71. throw EXCEPTION;
  72. }
  73. @Override
  74. public void feedBackEvent(Context context) {
  75. throw EXCEPTION;
  76. }
  77. }
  1. /**
  2. * 状态枚举类
  3. * @author Administrator
  4. *
  5. */
  6. public enum StateEnum {
  7. //订单生成
  8. GENERATE(1, "GENERATE"),
  9. //已审核
  10. REVIEWED(2, "REVIEWED"),
  11. //已发布
  12. PUBLISHED(3, "PUBLISHED"),
  13. //待付款
  14. NOT_PAY(4, "NOT_PAY"),
  15. //已付款
  16. PAID(5, "PAID"),
  17. //已完结
  18. FEED_BACKED(6, "FEED_BACKED");
  19. private int key;
  20. private String value;
  21. StateEnum(int key, String value) {
  22. this.key = key;
  23. this.value = value;
  24. }
  25. public int getKey() {return key;}
  26. public String getValue() {return value;}
  27. }
  1. //各种具体状态类
  2. class FeedBackState extends AbstractState {
  3. @Override
  4. public String getCurrentState() {
  5. return StateEnum.FEED_BACKED.getValue();
  6. }
  7. }
  8. class GenerateState extends AbstractState {
  9. @Override
  10. public void checkEvent(Context context) {
  11. context.setState(new ReviewState());
  12. }
  13. @Override
  14. public void checkFailEvent(Context context) {
  15. context.setState(new FeedBackState());
  16. }
  17. @Override
  18. public String getCurrentState() {
  19. return StateEnum.GENERATE.getValue();
  20. }
  21. }
  22. class NotPayState extends AbstractState {
  23. @Override
  24. public void payOrderEvent(Context context) {
  25. context.setState(new PaidState());
  26. }
  27. @Override
  28. public void feedBackEvent(Context context) {
  29. context.setState(new FeedBackState());
  30. }
  31. @Override
  32. public String getCurrentState() {
  33. return StateEnum.NOT_PAY.getValue();
  34. }
  35. }
  36. class PaidState extends AbstractState {
  37. @Override
  38. public void feedBackEvent(Context context) {
  39. context.setState(new FeedBackState());
  40. }
  41. @Override
  42. public String getCurrentState() {
  43. return StateEnum.PAID.getValue();
  44. }
  45. }
  46. class PublishState extends AbstractState {
  47. @Override
  48. public void acceptOrderEvent(Context context) {
  49. //把当前状态设置为 NotPayState。。。
  50. //至于应该变成哪个状态,有流程图来决定
  51. context.setState(new NotPayState());
  52. }
  53. @Override
  54. public void notPeopleAcceptEvent(Context context) {
  55. context.setState(new FeedBackState());
  56. }
  57. @Override
  58. public String getCurrentState() {
  59. return StateEnum.PUBLISHED.getValue();
  60. }
  61. }
  62. class ReviewState extends AbstractState {
  63. @Override
  64. public void makePriceEvent(Context context) {
  65. context.setState(new PublishState());
  66. }
  67. @Override
  68. public String getCurrentState() {
  69. return StateEnum.REVIEWED.getValue();
  70. }
  71. }
//环境上下文
public class Context extends AbstractState{
    //当前的状态 state, 根据我们的业务流程处理,不停的变化
    private State state;

    @Override
    public void checkEvent(Context context) {
        state.checkEvent(this);
        getCurrentState();
    }

    @Override
    public void checkFailEvent(Context context) {
        state.checkFailEvent(this);
        getCurrentState();
    }

    @Override
    public void makePriceEvent(Context context) {
        state.makePriceEvent(this);
        getCurrentState();
    }

    @Override
    public void acceptOrderEvent(Context context) {
        state.acceptOrderEvent(this);
        getCurrentState();
    }

    @Override
    public void notPeopleAcceptEvent(Context context) {
        state.notPeopleAcceptEvent(this);
        getCurrentState();
    }

    @Override
    public void payOrderEvent(Context context) {
        state.payOrderEvent(this);
        getCurrentState();
    }

    @Override
    public void orderFailureEvent(Context context) {
        state.orderFailureEvent(this);
        getCurrentState();
    }

    @Override
    public void feedBackEvent(Context context) {
        state.feedBackEvent(this);
        getCurrentState();
    }

    public State getState() {
        return state;
    }

    public void setState(State state) {
        this.state = state;
    }

    @Override
    public String getCurrentState() {
        System.out.println("当前状态 : " + state.getCurrentState());
        return state.getCurrentState();
    }
}

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //创建context 对象
        Context context = new Context();
        //将当前状态设置为 PublishState
        context.setState(new PublishState());
        System.out.println(context.getCurrentState());

//        //publish --> not pay
        context.acceptOrderEvent(context);
//        //not pay --> paid
        context.payOrderEvent(context);
//        // 失败, 检测失败时,会抛出异常
//        try {
//            context.checkFailEvent(context);
//            System.out.println("流程正常..");
//        } catch (Exception e) {
//            // TODO: handle exception
//            System.out.println(e.getMessage());
//        }

    }

注意事项

状态模式的注意事项和细节1) 代码有很强的可读性。状态模式将每个状态的行为封装到对应的一个类中
2) 方便维护。将容易产生问题的if-else语句删除了,如果把每个状态的行为都放到一
个类中,每次调用方法时都要判断当前是什么状态,不但会产出很多if-else语句,
而且容易出错
3) 符合“开闭原则”。容易增删状态
4) 会产生很多类。每个状态都要一个对应的类,当状态过多时会产生很多类,加大维
护难度
5) 应用场景:当一个事件或者对象有很多种状态,状态之间会相互转换,对不同的状
态要求有不同的行为的时候,可以考虑使用状态模式