2021年10月8日-设计模式之状态模式

第二十二章:状态模式

一、模式简介

一个事物有不同的状态,比如人有高兴、悲伤、生气等状态。人处于这些不同的状态会有不同的行为,如高兴时会唱歌、生气时会跺脚等等。而且这些状态会随着行为的发生而相互转换,如生气时跺脚人的状态就由生气转变为冷静。

如果我们在一个方法中使用 if 语句来描述这些状态的改变,势必会有大量 if 的嵌套,而且后续增加新的状态还要修改代码不符合开闭原则。

所以我们使用状态模式来代替 if 语句

基本类图:

在这里插入图片描述

  • State:抽象状态类,里面声明了各个行为
  • CurrentStateA、CurrentStateB:具体状态类,根据具体的状态,行为有不同的实现
  • Subject:状态的拥有者,currentState 指明了这个主体当前处于的状态

二、具体案例

我们使用尚硅谷的抽奖案例,因为一个比较好又比较容易实现的案例暂时没想到╮(╯-╰)╭

状态转移图:

在这里插入图片描述

我们根据上面的状态转移图来编程:

抽象 State 类

abstract public class State {
    abstract public void deduceScore();
    abstract public boolean raffle();
    abstract public void dispensePrize();
}

具体状态类

不能抽奖状态

public class NoRaffleState extends State {
    private Activity activity;

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

    @Override
    public void deduceScore() {
        if (this.activity.deduceScore()) {
            this.activity.setState(this.activity.getCanRaffleState());
        } else {
            System.out.println("积分不足,请充值");
        }
    }

    @Override
    public boolean raffle() {
        System.out.println("需要扣除积分,再抽奖");
        return false;
    }

    @Override
    public void dispensePrize() {
        System.out.println("需要先抽奖");
    }
}

能抽奖状态

public class CanRaffleState extends State {
    private Activity activity;

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

    @Override
    public void deduceScore() {
        System.out.println("已经扣过积分了,请抽奖");
    }

    @Override
    public boolean raffle() {
        Random random = new Random(new Date().getTime());
        int num = random.nextInt(10);
        if (num == 0) {
            activity.setState(activity.getDispenseState());
            return true;
        } else {
            activity.setState(activity.getNoRaffleState());
            return false;
        }
    }

    @Override
    public void dispensePrize() {
        System.out.println("需要先抽奖");
    }
}

发奖状态

public class DispenseState extends State {
    private Activity activity;

    public DispenseState(Activity activity) {
        this.activity = activity;
    }

    @Override
    public void deduceScore() {
        System.out.println("已经中奖了了,需要发奖");
    }

    @Override
    public boolean raffle() {
        System.out.println("已经中奖了了,需要发奖");
        return false;
    }

    @Override
    public void dispensePrize() {
        this.activity.subtractCount();
        if (this.activity.getCount() > 0) {
            this.activity.setState(this.activity.getNoRaffleState());
        } else {
            this.activity.setState(this.activity.getDispenseOutState());
        }
        System.out.println("恭喜中奖了");
    }
}

没有奖品状态

public class DispenseOutState extends State {
    private Activity activity;

    public DispenseOutState(Activity activity) {
        this.activity = activity;
    }

    @Override
    public void deduceScore() {
        System.out.println("没有奖品了,无法抽奖");
    }

    @Override
    public boolean raffle() {
        System.out.println("没有奖品了,无法抽奖");
        return false;
    }

    @Override
    public void dispensePrize() {
        System.out.println("没有奖品了,无法抽奖");
    }
}

状态拥有者

public class Activity {
    // 也可以使用单例模式或享元模式代替
    private State noRaffleState = new NoRaffleState(this);
    private State canRaffleState = new CanRaffleState(this);
    private State dispenseState = new DispenseState(this);
    private State dispenseOutState = new DispenseOutState(this);
    private State state;
    private int score;
    private int count;

    public Activity(int score, int count) {
        this.score = score;
        this.count = count;
        this.state = getNoRaffleState();
    }

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

    public State getNoRaffleState() {
        return noRaffleState;
    }

    public State getCanRaffleState() {
        return canRaffleState;
    }

    public State getDispenseState() {
        return dispenseState;
    }

    public State getDispenseOutState() {
        return dispenseOutState;
    }

    public int getScore() {
        return score;
    }

    public boolean deduceScore() {
        if (this.score >= 50) {
            this.score -= 50;
            return true;
        }
        return false;
    }

    public int getCount() {
        return count;
    }

    public void subtractCount() {
        this.count--;
    }

    public void run() {
        this.state.deduceScore();
        if (this.state.raffle()) {
            this.state.dispensePrize();
        } else {
            System.out.println("很遗憾,没有抽中");
        }
    }
}

测试抽奖

public class StateTest {
    public static void main(String[] args) {
        Activity activity = new Activity(300, 5);
        for (int i = 0; i < 10; i++) {
            activity.run();
        }
    }
}


/**********
很遗憾,没有抽中
很遗憾,没有抽中
很遗憾,没有抽中
很遗憾,没有抽中
很遗憾,没有抽中
很遗憾,没有抽中
积分不足,请充值
需要扣除积分,再抽奖
很遗憾,没有抽中
积分不足,请充值
需要扣除积分,再抽奖
很遗憾,没有抽中
积分不足,请充值
需要扣除积分,再抽奖
很遗憾,没有抽中
积分不足,请充值
需要扣除积分,再抽奖
很遗憾,没有抽中
**********/

三、模式总结

优点:

  • 可读性强
  • 方便维护,不用 if 语句来判断现在处于哪个状态

缺点:

  • 有很多状态类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值