设计模式 -- 状态模式(State Pattern)

允许一个对象在内部状态改变时改变它的行为。

应用场景

  • 一个对象的行为取决于它的状态,并且它在运行时根据状态改变它的行为。

  • 代码中包含大量与对象状态相关的判断语句。

优点:

  • 将不同的状态隔离

  • 把各种状态的转换逻辑,分布到State的子类中,减少相互间依赖

  • 增加新的状态非常简单

状态模式与责任链模式的区别

状态模式和责任链模式都能消除 if-else 分支过多的问题。但在某些情况下,状态模式中的状态可以理解为责任,那么在这种情况下,两种模式都可以使用。

从定义来看,状态模式强调的是一个对象内在状态的改变,而责任链模式强调的是外部节点对象间的改变。

从代码实现上来看,两者最大的区别就是状态模式的各个状态对象知道自己要进入的下一个状态对象,而责任链模式并不清楚其下一个节点处理对象,因为链式组装由客户端负责。

状态模式与策略模式的区别

状态模式和策略模式的 UML 类图架构几乎完全一样,但两者的应用场景是不一样的。策略模式的多种算法行为择其一都能满足,彼此之间是独立的,用户可自行更换策略算法,而状态模式的各个状态间存在相互关系,彼此之间在一定条件下存在自动切换状态的效果,并且用户无法指定状态,只能设置初始状态。

当使用Context类切换状态时,状态类之间互相不认识,他们直接的依赖关系应该由客户端负责。

当使用具体的State类切换时,状态直接就可能互相认识,一个状态执行完就自动切换到了另一个状态去了

用Context类切换状态

设计模式 -- 状态模式(State Pattern)_第1张图片

买键盘,物流系统就很适合使用状态模式来开发,因为此过程存在很多不同的状态,例如接单,出库,运输,送货,收货,评价等等。而订单在每个不同的状态下的操作可能都不一样。

设计模式 -- 状态模式(State Pattern)_第2张图片

// 定义一个状态接口
public interface LogisticsState {
    void doAction(JdLogistics context);
}


// 定义一个物流Context类
// 此类持有一个LogisticsState 的引用,负责在流程中保持并切换状态
public class JdLogistics {
    private LogisticsState logisticsState;

    public void setLogisticsState(LogisticsState logisticsState) {
        this.logisticsState = logisticsState;
    }

    public LogisticsState getLogisticsState() {
        return logisticsState;
    }
    
    public void doAction(){
        Objects.requireNonNull(logisticsState);
        logisticsState.doAction(this);
    }
}


//接单状态类 
public class OrderState implements LogisticsState {
    @Override
    public void doAction(JdLogistics context) {
        System.out.println("商家已经接单,正在处理中...");
    }
}


// 出库状态类
public class ProductOutState implements LogisticsState {
    @Override
    public void doAction(JdLogistics context) {
        System.out.println("商品已经出库...");
    }
}


// 运输状态类
public class TransportState implements LogisticsState {
    @Override
    public void doAction(JdLogistics context) {
        System.out.println("商品正在运往天津分发中心");
    }
}


// 客户端使用
public class StateClient {

    public void buyKeyboard() {
        //状态的保持与切换者
        JdLogistics jdLogistics = new JdLogistics();

        //接单状态
        OrderState orderState = new OrderState();
        jdLogistics.setLogisticsState(orderState);
        jdLogistics.doAction();

        //出库状态
        ProductOutState productOutState = new ProductOutState();
        jdLogistics.setLogisticsState(productOutState);
        jdLogistics.doAction();

        //运输状态
        TransportState transportState = new TransportState();
        jdLogistics.setLogisticsState(transportState);
        jdLogistics.doAction();
    }
}


// 输出结果:
商家已经接单,正在处理中...
商品已经出库...
商品正在运往天津分发中心

用具体的State类切换状态

设计模式 -- 状态模式(State Pattern)_第3张图片

设计模式 -- 状态模式(State Pattern)_第4张图片

设计模式 -- 状态模式(State Pattern)_第5张图片

public class ScoreStateTest {
    public static void main(String[] args) {
        ScoreContext account = new ScoreContext();
        System.out.println("学生成绩状态测试:");
        account.add(30);
        account.add(40);
        account.add(25);
        account.add(-15);
        account.add(-25);
    }
}


//环境类
class ScoreContext {
    private AbstractState state;

    public void add(int score) {
        state.addScore(score);
    }
}


//抽象状态类
abstract class AbstractState {
    protected ScoreContext hj;  //环境
    protected int score; //分数

    public abstract void checkState(); //检查当前状态

    public void addScore(int x) {
        score += x;
        System.out.print("加上:" + x + "分,\t当前分数:" + score);
        checkState();
        System.out.println("分,\t当前状态:" + hj.getState().stateName);
    }
}


//具体状态类:不及格
class LowState extends AbstractState {
    public void checkState() {
        if (score >= 90) {
            hj.setState(new HighState(this));
        } else if (score >= 60) {
            hj.setState(new MiddleState(this));
        }
    }
}


//具体状态类:中等
class MiddleState extends AbstractState {
    public void checkState() {
        if (score >= 90) {
            hj.setState(new HighState(this));
        }
    }
}


//具体状态类:优秀
class HighState extends AbstractState {
    public void checkState() {
        
    }
}


设计模式 -- 状态模式(State Pattern)_第6张图片

设计模式 -- 状态模式(State Pattern)_第7张图片

CourseVideoContext类

设计模式 -- 状态模式(State Pattern)_第8张图片

设计模式 -- 状态模式(State Pattern)_第9张图片

设计模式 -- 状态模式(State Pattern)_第10张图片

PlayState类

设计模式 -- 状态模式(State Pattern)_第11张图片

设计模式 -- 状态模式(State Pattern)_第12张图片

设计模式 -- 状态模式(State Pattern)_第13张图片

SpeedState类

设计模式 -- 状态模式(State Pattern)_第14张图片

PauseState类

设计模式 -- 状态模式(State Pattern)_第15张图片

StopState类

设计模式 -- 状态模式(State Pattern)_第16张图片

Test类

设计模式 -- 状态模式(State Pattern)_第17张图片

JSF中的应用

在 JSF 中,所有页面的处理分为 7 个阶段,被定义在 PhaseId 类中,分别用不同的常量来表示周期阶段,

private class PhaseId implements Comparable {
    ...
    private static final PhaseId[] values = {
        ANY_PHASE,    // 任意一个生命周期阶段
        RESTORE_VIEW,    // 恢复视图阶段
        APPLY_REQUEST_VALUES,    // 应用请求值阶段
        PROCESS_VALIDATIONS,    // 处理输入校验阶段
        UPDATE_MODEL_VALUES,    // 更新模型的值阶段
        INVOKE_APPLICATION,    // 调用应用阶段
        RENDER_RESPONSE    // 显示响应阶段
    };
    ...
}

这些状态的切换都在 Lifecycle 类的 execute() 方法中进行,其中会传入一个参数 FacesContext 对象,最终所有状态都被 FacesContext 保存。

在有些情况下,可能有多个环境对象需要共享一组状态,这时需要引入享元模式,将这些具体状态对象放在集合中供程序共享。

设计模式 -- 状态模式(State Pattern)_第18张图片

//环境类
class ShareContext {
    private HashMap stateSet = new HashMap();

    public ShareContext() {
        state = new ConcreteState1();
        stateSet.put("1", state);
        state = new ConcreteState2();
        stateSet.put("2", state);
        state = getState("1");
    }

    //对请求做处理
    public void Handle() {
        state.Handle(this);
    }
}


//具体状态1类
class ConcreteState1 extends ShareState {
    public void Handle(ShareContext context) {
        System.out.println("当前状态是: 状态1");
        context.setState(context.getState("2"));
    }
}


//具体状态2类
class ConcreteState2 extends ShareState {
    public void Handle(ShareContext context) {
        System.out.println("当前状态是: 状态2");
        context.setState(context.getState("1"));
    }
}


根据以下文章总结:

  1. Java设计模式:23种设计模式全面解析(超级详细)HYPERLINK http://c.biancheng.net/design_pattern/ 

  2. 3种设计模式详解 https://www.iteye.com/blog/zz563143188-1847029 

  3. Android系统编程思想:设计模式https://github.com/sucese/android-open-source-project-analysis/blob/master/doc/Android%E7%B3%BB%E7%BB%9F%E8%BD%AF%E4%BB%B6%E8%AE%BE%E8%AE%A1%E7%AF%87/02Android%E7%B3%BB%E7%BB%9F%E8%BD%AF%E4%BB%B6%E8%AE%BE%E8%AE%A1%E7%AF%87%EF%BC%9A%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F.md#35-%E8%A7%82%E5%AF%9F%E8%80%85%E6%A8%A1%E5%BC%8F

  4. 设计模式 https://blog.csdn.net/shusheng0007/category_8638565.html

  5. java设计模式 https://blog.csdn.net/qq_37909508/category_8976362.html

  6. 设计模式 https://www.cnblogs.com/zuoxiaolong/category/509144.html 

  7. 设计模式 在源码中的应用 https://blog.csdn.net/qq_36970993/category_10620886.html

  8. Android系统设计中存在设计模式分析 https://www.2cto.com/kf/201208/150650.html

  9. Android设计模式系列 - 基于android的各种代码分析各种设计模式 https://www.cnblogs.com/qianxudetianxia/category/312863.html 

你可能感兴趣的:(设计模式,设计模式,状态模式)