一、状态模式基本介绍

  1、基本介绍

    (1)状态模式(State Pattern):它主要用来解决对象在多种状态转换时,需要对外输出不同的行为的问题。状态和行为是一一对应的,状态之间可以相互转换;

    (2)当一个对象的内在状态改变时,允许改变其行为,这个对象看起来像是改变了其类;

  2、状态模式的原理类图

 

     对原理类图的说明——即(状态模式的角色及职责)

    (1)Context 类为环境角色,用于维护 State 实例,这个实例定义当前状态;

    (2)State 是抽象状态角色,定义一个接口封装与 Context 的一个特点接口相关行为;

    (3)ConcreteState 具体的状态角色,每个子类实现一个与 Context 的一个状态相关行为;

 

二、状态模式解决 APP抽奖问题

  1、应用实例要求

    完成 APP 抽奖活动项目,使用状态模式

  2、思路分析和图解

    定义出一个接口叫状态接口,每个状态都实现它。

    接口有扣除积分方法、抽奖方法、发放奖品方法。

    

 

  3、代码实现

    状态接口类:

 1 /**
 2  * 状态 接口
 3  */
 4 public interface State {
 5 
 6     /**
 7      * 扣除积分  - 50
 8      */
 9     public void deductMoney();
10 
11     /**
12      * 是否抽中奖品
13      * @return
14      */
15     public boolean raffle();
16 
17 
18     /**
19      * 发放奖品
20      */
21     public void dispensePrize();
22 }

 

    各个状态实现类:

  1 /**
  2  * 不能抽奖状态
  3  */
  4 public class NoRaffleState implements State{
  5 
  6     /**
  7      * 初始化时传入活动引用,扣除积分后改变其状态
  8      */
  9     RaffleActivity activity;
 10 
 11     public NoRaffleState(RaffleActivity activity) {
 12         this.activity = activity;
 13     }
 14 
 15     /**
 16      * 当前状态可以扣积分,扣除后,将状态设置成可以抽奖状态
 17      */
 18     @Override
 19     public void deductMoney() {
 20         System.out.println("扣除50积分成功,您可以抽奖了");
 21         activity.setState(activity.getCanRaffleState());
 22     }
 23 
 24     /**
 25      * 抽奖,当前状态是不能抽奖的
 26      * @return
 27      */
 28     @Override
 29     public boolean raffle() {
 30         System.out.println("扣了积分才能抽奖哦!");
 31         return false;
 32     }
 33 
 34     @Override
 35     public void dispensePrize() {
 36         System.out.println("不能发放奖品");
 37     }
 38 }
 39 ------------------------------------------------------
 40 /**
 41  * 可以抽奖的状态
 42  */
 43 public class CanRaffleState implements State{
 44 
 45     /**
 46      * 初始化时传入活动引用,扣除积分后改变其状态
 47      */
 48     RaffleActivity activity;
 49 
 50     public CanRaffleState(RaffleActivity activity) {
 51         this.activity = activity;
 52     }
 53 
 54     @Override
 55     public void deductMoney() {
 56         System.out.println("已经扣取过了积分");
 57     }
 58 
 59     /**
 60      * 可以抽奖,抽完奖后,根据实际情况,设置新的状态
 61      * @return
 62      */
 63     @Override
 64     public boolean raffle() {
 65         System.out.println("正在抽奖,请稍等!");
 66         Random random = new Random();
 67         int num = random.nextInt(10);
 68         if (num == 0) {
 69             //改变活动状态为发放奖品 context
 70             activity.setState(activity.getDispenseState());
 71             return true;
 72         }else {
 73             System.out.println("很遗憾没有抽中奖品!");
 74             //改变状态为不能抽奖
 75             activity.setState(activity.getNoRaffleState());
 76             return false;
 77         }
 78     }
 79 
 80     /**
 81      * 不能发放奖品
 82      */
 83     @Override
 84     public void dispensePrize() {
 85         System.out.println("没有中奖,不能发放奖品");
 86     }
 87 }
 88 ------------------------------------------------------
 89 /**
 90  * 发送奖品的状态
 91  */
 92 public class DispenseState implements State{
 93 
 94     /**
 95      * 初始化时传入活动引用,扣除积分后改变其状态
 96      */
 97     RaffleActivity activity;
 98 
 99     public DispenseState(RaffleActivity activity) {
100         this.activity = activity;
101     }
102 
103     /**
104      * 不能扣除积分
105      */
106     @Override
107     public void deductMoney() {
108         System.out.println("不能扣除积分");
109     }
110 
111     /**
112      * 不能抽奖
113      * @return
114      */
115     @Override
116     public boolean raffle() {
117         System.out.println("不能抽奖");
118         return false;
119     }
120 
121     /**
122      * 发放奖品
123      */
124     @Override
125     public void dispensePrize() {
126         if (activity.getCount() > 0) {
127             System.out.println("恭喜中奖了!");
128             // 改变状态为不能抽奖
129             activity.setState(activity.getNoRaffleState());
130         }else {
131             System.out.println("很遗憾,奖品发送完了");
132             //改变状态为奖品发送完毕,后面就不可以再抽奖了
133             activity.setState(activity.getDispenseOutState());
134             System.out.println("抽奖结束,多谢参与");
135             System.exit(0);
136         }
137     }
138 }
139 ------------------------------------------------------
140 /**
141  * 奖品发放完毕状态
142  * 说明:当我们 activity 改变成 DispenseOutState,抽奖活动结束了
143  */
144 public class DispenseOutState implements State{
145 
146     /**
147      * 初始化时传入活动引用,扣除积分后改变其状态
148      */
149     RaffleActivity activity;
150 
151     public DispenseOutState(RaffleActivity activity) {
152         this.activity = activity;
153     }
154 
155     @Override
156     public void deductMoney() {
157         System.out.println("奖品发送完了,请下次再参加");
158     }
159 
160     @Override
161     public boolean raffle() {
162         System.out.println("奖品发送完了,请下次再参加");
163         return false;
164     }
165 
166     @Override
167     public void dispensePrize() {
168         System.out.println("奖品发送完了,请下次再参加");
169     }
170 }

 

    Context 上下文对象:

  1 /**
  2  * 抽奖活动
  3  */
  4 public class RaffleActivity {
  5 
  6     /**
  7      * 表示当前的状态,是变化的
  8      */
  9     private State state = null;
 10 
 11     /**
 12      * 奖品数量
 13      */
 14     int count = 0;
 15 
 16     /**
 17      * 下面四个属性,表示四种状态
 18      */
 19     State noRaffleState = new NoRaffleState(this);
 20     State canRaffleState = new CanRaffleState(this);
 21     State dispenseState = new DispenseState(this);
 22     State dispenseOutState = new DispenseOutState(this);
 23 
 24     /**
 25      * 构造器
 26      *  1、初始化当前的状态为 noRaffleState 不能抽奖的状态
 27      *  2、初始化奖品的数量
 28      * @param count
 29      */
 30     public RaffleActivity(int count) {
 31         this.state = getNoRaffleState();
 32         this.count = count;
 33     }
 34 
 35     /**
 36      * 扣分,调用当前状态的 deductMoney
 37      */
 38     public void debuctMoney() {
 39         state.deductMoney();
 40     }
 41 
 42     /**
 43      * 抽奖
 44      */
 45     public void raffle() {
 46         //如果当前的状态是抽奖成功
 47         if (state.raffle()) {
 48             //领取奖品
 49             state.dispensePrize();
 50         }
 51     }
 52 
 53 
 54 
 55 
 56 
 57     public State getState() {
 58         return state;
 59     }
 60 
 61     public void setState(State state) {
 62         this.state = state;
 63     }
 64 
 65 
 66     /**
 67      * 注意:每领取一次奖品,count--
 68      * @param
 69      */
 70     public int getCount() {
 71         int curCount = count;
 72         count--;
 73         return curCount;
 74     }
 75 
 76     public void setCount(int count) {
 77         this.count = count;
 78     }
 79 
 80     public State getNoRaffleState() {
 81         return noRaffleState;
 82     }
 83 
 84     public void setNoRaffleState(State noRaffleState) {
 85         this.noRaffleState = noRaffleState;
 86     }
 87 
 88     public State getCanRaffleState() {
 89         return canRaffleState;
 90     }
 91 
 92     public void setCanRaffleState(State canRaffleState) {
 93         this.canRaffleState = canRaffleState;
 94     }
 95 
 96     public State getDispenseState() {
 97         return dispenseState;
 98     }
 99 
100     public void setDispenseState(State dispenseState) {
101         this.dispenseState = dispenseState;
102     }
103 
104     public State getDispenseOutState() {
105         return dispenseOutState;
106     }
107 
108     public void setDispenseOutState(State dispenseOutState) {
109         this.dispenseOutState = dispenseOutState;
110     }
111 }

 

    客户端:

 1 public class Client {
 2     public static void main(String[] args) {
 3         RaffleActivity activity = new RaffleActivity(1);
 4 
 5         for (int i = 0; i < 30; i++) {
 6             System.out.println("-----第" + (i + 1) + "次抽奖-----");
 7             //参加抽奖,第一步点击扣除积分
 8             activity.debuctMoney();
 9 
10             //第二步抽奖
11             activity.raffle();
12         }
13     }
14 }

 

  

 

posted on 2021-03-01 22:01  格物致知_Tony  阅读(273)  评论(0编辑  收藏  举报