@[TOC]

introduce

  1. State pattern: It is mainly used to solve the problem that the object needs to output different behaviors when converting between various states. The State and behavior are one-to-one corresponding, and states can be converted to each other.
  2. Allowing an object to change its behavior when its internal state changes, the object appears to change other classes.

  • Context: An environment role that maintains an instance of the ConcreteState subclass that defines the current state.
  • State: Defines an interface for the abstract State role to encapsulate the behavior associated with a particular interface State of the Context.
  • ConcreateState: Concrete state roles. Each subclass implements an action related to a state of the Context.

case

Lucky draw:

  1. If 50 points are deducted for every time you participate in the event, the chance of winning is 10%
  2. There is a fixed number of prizes and no prizes can be drawn
  3. Activities and four states: can draw, can not draw, distribute prizes and prizes have been collected

Creating the RaffleActivity class is equivalent to a Context in state mode

public class RaffleActivity {

    State state;

    int count = 0;

    State noRaffleState = new NoRaffleState(this);
    State canRaffleState = new CanRaffleState(this);
    State dispenseState = new DispenseState(this);
    State dispenseOutState = new DispenseOutState(this);

    public RaffleActivity(int count) {
        this.state = getNoRaffleState();
        this.count = count;
    }



    public void debuctMoney(a){
        state.deductMoney();
    }

    public void raffle(a){
        if(state.raffle()){ state.dispensePrize(); }}public int getCount(a){
        int curCount = count;
        count-- ;
        return curCount;
    }

    public void setCount(int COunt){
        this.count = count;
    }

    public void setNoRaffleState(State noRaffleState) {
        this.noRaffleState = noRaffleState;
    }

    State getNoRaffleState(a) {
        return noRaffleState;
    }

    public State getCanRaffleState(a) {
        return canRaffleState;
    }

    public void setCanRaffleState(State canRaffleState) {
        this.canRaffleState = canRaffleState;
    }

    public State getDispenseState(a) {
        return dispenseState;
    }

    public void setDispenseState(State dispenseState) {
        this.dispenseState = dispenseState;
    }

    public State getDispenseOutState(a) {
        return dispenseOutState;
    }

    public void setDispenseOutState(State dispenseOutState) {
        this.dispenseOutState = dispenseOutState;
    }

    public State getState(a) {
        return state;
    }

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

Creating an Abstract Interface

public abstract class State {

    /** * deducts the integral */
    public abstract void deductMoney(a);

    /** * Whether to draw the prize */
    public abstract boolean raffle(a);

    /** ** distribute prizes */
    public abstract void dispensePrize(a);



}

Copy the code

Create the initialization sweepstakes NoRaffleState class inherits State

public class NoRaffleState extends State{

    // Initialize the activity reference
    RaffleActivity raffleActivity;

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

    @Override
    public void deductMoney(a) {
        System.out.println("Deduct 50 points for a draw.");
        raffleActivity.setState(raffleActivity.getCanRaffleState());
    }

    @Override
    public boolean raffle(a) {
        System.out.println("Enter points to draw.");
        return false;
    }

    @Override
    public void dispensePrize(a) {
        System.out.println("Cannot distribute prizes in current state"); }}Copy the code

Create a raffle CanRaffleState class that inherits State

public class CanRaffleState extends State{

    // Initialize the activity reference
    RaffleActivity raffleActivity;

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

    @Override
    public void deductMoney(a) {
        System.out.println("The points have been deducted.");
    }

    @Override
    public boolean raffle(a) {
        System.out.println("Raffle going on...");
        Random r = new Random();
        int num = r.nextInt(10);
        if(num == 0){
            System.out.println("Won the lottery.");
            raffleActivity.setState(raffleActivity.getDispenseState());
            // Distribute prizes
            return true;
        }else {
            System.out.println("Unfortunately, I didn't win.");
            raffleActivity.setState(raffleActivity.getNoRaffleState());
            return false; }}@Override
    public void dispensePrize(a) {
        System.out.println("No prizes can be given."); }}Copy the code

Create the distribute raffle DispenseState class inherits State

public class DispenseState extends State{

    // Initialize the activity reference
    RaffleActivity raffleActivity;

    public DispenseState(RaffleActivity raffleActivity) {
        this.raffleActivity = raffleActivity;
    }

    @Override
    public void deductMoney(a) {
        System.out.println("No points deducted.");
    }

    @Override
    public boolean raffle(a) {
        System.out.println("No raffle.");
        return false;
    }

    @Override
    public void dispensePrize(a) {
        if (raffleActivity.getCount() > 0){
            raffleActivity.setState(raffleActivity.getNoRaffleState());
        }else{
            System.out.println("All the prizes are distributed."); raffleActivity.setState(raffleActivity.getDispenseState()); }}}Copy the code

Create a sweepstakes distribution to complete the DispenseOutState class inheriting State

public class DispenseOutState extends State{

    // Initialize the activity reference
    RaffleActivity raffleActivity;

    public DispenseOutState(RaffleActivity raffleActivity) {
        this.raffleActivity = raffleActivity;
    }


    @Override
    public void deductMoney(a) {
        System.out.println("The prize has been sent. Next time.");
    }

    @Override
    public boolean raffle(a) {
        System.out.println("The prize has been sent. Next time.");
        return false;
    }

    @Override
    public void dispensePrize(a) {
        System.out.println("The prize has been sent. Next time."); }}Copy the code

The client

public class Client {

    public static void main(String[] args) {
        RaffleActivity raffleActivity = new RaffleActivity(1);
        for (int i = 1; i < 10; i++) {
            System.out.println("-- -- -- -- -- -- -- -- -- -- the first" +i+"This lucky draw ---------");
            / / pointsraffleActivity.debuctMoney(); raffleActivity.raffle(); }}}Copy the code

Advantages and disadvantages

Advantages:

1) Clear structure, avoiding too many switches... The case or the if... The use of else statements 2) well reflects the open closed principle and the single responsibility principle, if you want to increase the state to add a subclass, if you want to change the state to modify the subclass can be modified 3) encapsulation is very good, state changes are placed inside the class to implement, external calls do not need to know how to implement state and behavior changes inside the classCopy the code

Disadvantages:

1) There will be too many subclasses, i.e. class inflationCopy the code

Applicable scenarios:

1) a scenario in which behavior changes with state changes, such as: one's own state from morning to night, such as working state, learning state, etc. 2) substitution of conditional and branch judgment statementsCopy the code



Github Demo address: ~ ~ ~ portal ~ ~ ~

Personal blog address: blog.yanxiaolu.cn /