State Pattern

APP lottery issues

Please write a program to complete the APP lucky draw. The specific requirements are as follows:

  1. If 50 points are deducted from the user for each participation in this activity, the probability of winning is 10%

  2. The number of prizes is fixed and the draw cannot be drawn

  3. There are four statuses in the activity: Lottery can be drawn, Lottery can not be drawn, prizes are issued, and prizes finished

  4. The four state transition diagrams of activities (below)
    Insert picture description here

Basic introduction to state mode

basic introduction

  1. State Pattern: It is mainly used to solve the problem that objects need to output different behaviors when they are in a variety of state transitions. There is a one-to-one correspondence between state and behavior, and the states can be converted to each other

  2. Be aWhen the internal state of the object changes, it is allowed to change its behavior, This object looks like it has changed its class

Schematic diagram of the state pattern

Insert picture description here

  • Description of the schematic diagram-namely (role and responsibilities of the state model)
  1. ContextThe class is an environmental role , used to maintain a State instance, which defines the current state (aggregate State)

  2. StateIt is an abstract state role that defines an interface to encapsulate a characteristic interface-related behavior of Context

  3. ConcreteState Specific state roles , each subclass implements a state-related behavior related to Context

State mode solves the APP lottery problem

  1. The application example requires the
    completion of the APP lucky draw project, using the state mode.
  2. Idea analysis and illustration (class diagram)
    Insert picture description here
    -Define an interface called a state interface, and each state implements it.
    -The interface has points deduction method, lottery method, and prize distribution method
  3. Code

Client:

/**
 * 状态模式测试类
 * @author Administrator
 *
 */
public class ClientTest {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		// 创建活动对象,奖品有1个奖品
        RaffleActivity activity = new RaffleActivity(1);

        // 我们连续抽300次奖
        for (int i = 0; i < 30; i++) {
    
    
            System.out.println("--------第" + (i + 1) + "次抽奖----------");
            // 参加抽奖,第一步点击扣除积分
            activity.debuctMoney();

            // 第二步抽奖
            activity.raffle();
        }
	}

}

Sweepstakes, context

/**
 * 抽奖活动 //
 * 
 * @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.deductMoney();
    }

    //抽奖 
    public void raffle(){
    
    
    	// 如果当前的状态是抽奖成功
        if(state.raffle()){
    
    
        	//领取奖品
            state.dispensePrize();
        }

    }

    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;
    }
}
/**
 * 状态抽象类
 * @author Administrator
 *
 */
public abstract class State {
    
    

	
	// 扣除积分 - 50
    public abstract void deductMoney();

    // 是否抽中奖品
    public abstract boolean raffle();

    // 发放奖品
    public abstract  void dispensePrize();

}
import java.util.Random;

/**
 * 可以抽奖的状态
 * @author Administrator
 *
 */
public class CanRaffleState extends State {
    
    

    RaffleActivity activity;

    public CanRaffleState(RaffleActivity activity) {
    
    
        this.activity = activity;
    }

    //已经扣除了积分,不能再扣
    @Override
    public void deductMoney() {
    
    
        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 dispensePrize() {
    
    
        System.out.println("没中奖,不能发放奖品");
    }
}
/**
 * 奖品发放完毕状态
 * 说明,当我们activity 改变成 DispenseOutState, 抽奖活动结束
 * @author Administrator
 *
 */
public class DispenseOutState extends State {
    
    

	// 初始化时传入活动引用
    RaffleActivity activity;

    public DispenseOutState(RaffleActivity activity) {
    
    
        this.activity = activity;
    }
    @Override
    public void deductMoney() {
    
    
        System.out.println("奖品发送完了,请下次再参加");
    }

    @Override
    public boolean raffle() {
    
    
        System.out.println("奖品发送完了,请下次再参加");
        return false;
    }

    @Override
    public void dispensePrize() {
    
    
        System.out.println("奖品发送完了,请下次再参加");
    }
}
/**
 * 发放奖品的状态
 * @author Administrator
 *
 */
public class DispenseState extends State {
    
    

	 // 初始化时传入活动引用,发放奖品后改变其状态
    RaffleActivity activity;

    public DispenseState(RaffleActivity activity) {
    
    
        this.activity = activity;
    }
    
    //

    @Override
    public void deductMoney() {
    
    
        System.out.println("不能扣除积分");
    }

    @Override
    public boolean raffle() {
    
    
        System.out.println("不能抽奖");
        return false;
    }

    //发放奖品
    @Override
    public void dispensePrize() {
    
    
        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);
        }

    }
}
/**
 * 不能抽奖状态
 * @author Administrator
 *
 */
public class NoRaffleState extends State {
    
    

	 // 初始化时传入活动引用,扣除积分后改变其状态
    RaffleActivity activity;

    public NoRaffleState(RaffleActivity activity) {
    
    
        this.activity = activity;
    }

    // 当前状态可以扣积分 , 扣除后,将状态设置成可以抽奖状态
    @Override
    public void deductMoney() {
    
    
        System.out.println("扣除50积分成功,您可以抽奖了");
        activity.setState(activity.getCanRaffleState());
    }

    // 当前状态不能抽奖
    @Override
    public boolean raffle() {
    
    
        System.out.println("扣了积分才能抽奖喔!");
        return false;
    }

    // 当前状态不能发奖品
    @Override
    public void dispensePrize() {
    
    
        System.out.println("不能发放奖品");
    }
}

Notes and details of state mode

  1. The code is very readable . State mode encapsulates the behavior of each state into a corresponding class

  2. Easy to maintain . The if-else statement that is prone to problems is deleted. If the behavior of each state is placed in a class, the current state must be judged every time the method is called.Not only will it produce a lot of if-else statementsAnd error-prone

  3. Comply with the "opening and closing principle". Easy to add or delete status

  4. Many classes will be generated. Each state must have a corresponding class. When there are too many states, many classes will be generated, increasing the difficulty of maintenance

  5. Application scenario: When an event or object has many states, the states will switch to each other, and different states require different behaviors, you can consider using state mode

to sum up

First analyze: There are state analysis diagrams, there are several states, how about each state

Guess you like

Origin blog.csdn.net/weixin_46168350/article/details/111500907