南通兼职网:行为型设计模式 - 状态模式详解

admin 4个月前 (05-16) 科技 33 0

基本先容

状态模式(State Pattern)主要用来解决工具在多种状态转换时,需要对外输出差别的行为的问题,类的行为是基于它的状态改变的。

模式结构

Context(环境角色):用于维护 State 实例,这个实例界说当前状态

State(抽象状态):界说一个接口以封装与 Context 的一个特定状态相关的行为

ConcreteState(详细状态):每一子类实现一个与 Context 的一个状态相关的行为

举例说明

我们以抽奖的场景作为例子,流程如下:

界说一个抽象状态:State

public interface State {
    RuntimeException EXCEPTION = new RuntimeException("不能执行此操作");

    /**
     * 报名
     */
    default void signUp() {
        throw EXCEPTION;
    }

    /**
     * 抽奖
     */
    default boolean raffle() {
        throw EXCEPTION;
    }

    /**
     * 发奖品
     */
    default void sendPrize() {
        throw EXCEPTION;
    }
}

详细状态1:不能抽奖

public class NotRaffleState implements State {

    private RaffleActivity activity;

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

    @Override
    public void signUp() {
        //若是没有奖品,直接进入无奖品状态
        if (!activity.hasPrize()) {
            activity.setState(activity.getNoPrizeState());
            return;
        }
        System.out.println("报名乐成,可以抽奖了");
        activity.setState(activity.getCanRaffleState());
    }
}

详细状态2:可以抽奖

public class CanRaffleState implements State {

    private RaffleActivity activity;

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

    @Override
    public boolean raffle() {
        //模拟五分之一的中奖几率
        int n = new Random().nextInt(5);
        if (n == 0) {
            //抽中,进入发放奖品的状态
            System.out.println("恭喜你,抽中了");
            activity.setState(activity.getSendPrizeState());
            return true;
        } else {
            //未抽中,回到初始状态
            System.out.println("很遗憾,没有抽中");
            activity.setState(activity.getNotRaffleState());
            return false;
        }
    }
}

详细状态3:发放奖品

public class SendPrizeState implements State {

    private RaffleActivity activity;

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

    @Override
    public void sendPrize() {
        int count = activity.getCount();
        //没有奖品了
        if (count <= 0) {
            System.out.println("奖品没有了,下次再来吧");
            activity.setState(activity.getNoPrizeState());
        } else {
            activity.setCount(--count);
            System.out.println("奖品已发送");
            activity.setState(activity.getNotRaffleState());
        }
    }
}

详细状态4:奖品领完

public class NoPrizeState implements State {

    private RaffleActivity activity;

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

    @Override
    public void signUp() {
        System.out.println("奖品没有了,下次再来吧");
        System.exit(0);
    }

    @Override
    public boolean raffle() {
        System.out.println("奖品没有了,下次再来吧");
        System.exit(0);
        return false;
    }

    @Override
    public void sendPrize() {
        System.out.println("奖品没有了,下次再来吧");
        System.exit(0);
    }
}

环境角色:抽奖流动

public class RaffleActivity {
    private State state;
    private int count;
    private State notRaffleState = new NotRaffleState(this);
    private State canRaffleState = new CanRaffleState(this);
    private State sendPrizeState = new SendPrizeState(this);
    private State noPrizeState = new NoPrizeState(this);

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

    public void signUp() {
        state.signUp();
    }

    public void raffle() {
        if (state.raffle()) {
            state.sendPrize();
        }
    }

    public State getState() {
        return state;
    }

    public boolean hasPrize(){
        return count > 0;
    }
    //省略getter、setter
}

客户端

public class Client {
    @Test
    public void test(){
        RaffleActivity activity = new RaffleActivity(1);
        for (int i = 0; i < 5; i++) {
            System.out.println("第" + (i + 1) + "次抽奖");
            activity.signUp();
            activity.raffle();
            System.out.println("------------------");
        }
    }
}

运行效果

第1次抽奖
报名乐成,可以抽奖了
很遗憾,没有抽中
------------------
第2次抽奖
报名乐成,可以抽奖了
恭喜你,抽中了
奖品已发送
------------------
第3次抽奖
奖品没有了,下次再来吧

模式剖析

优点:

  • 代码具有较强的可读性。状态模式将每个状态的行为封装到对应的一个类中
  • 利便维护。将容易发生问题的 if-else 语句删除了,若是把每个状态的行为都放到一个类中,每次挪用方式时都要判断当前是什么状态,不但会产出许多 if-else 语句,而且容易失足

瑕玷:

  • 会发生许多类。每个状态都对应一个类,当状态过多时,维护难度变大
  • 状态模式的结构与实现都较为庞大,若是使用不当将导致程序结构和代码的杂乱
  • 状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增添新的状态类需要修改那些卖力状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

适用环境:

  • 行为随状态改变而改变的场景

  • 条件、分支语句的取代者

,

诚信在线

诚信在线(www.aidshuhehaote.com)现已开放诚信在线手机版下载。游戏公平、公开、公正,用实力赢取信誉。

欧博开户声明:该文看法仅代表作者自己,与本平台无关。转载请注明:南通兼职网:行为型设计模式 - 状态模式详解

网友评论

  • (*)

最新评论

文章归档

站点信息

  • 文章总数:444
  • 页面总数:0
  • 分类总数:8
  • 标签总数:980
  • 评论总数:105
  • 浏览总数:2752