聊聊设计模式-状态模式 | 思维导图系统化学习

154 阅读3分钟

设计模式-状态模式

既然谈到状态模式,那么我们就很有必要探讨一个问题

什么是状态?

具体到代码中,就是对象内部的变量处于的阶段,所谓阶段是由具体业务定义的。

statechange.png

现实例子

我们就以大多数人都经过的学历为例子

stateDiagram-v2

高中 --> 专科

高中 --> 本科
专科 --> 本科


本科 --> 研究生
专科 --> 研究生

高考结束了,有的同学通过高考进入了专科学习,有些同学进入了本科学习,也有些同学选择复读仍在高中学习......
专科学习的同学通过专升本可以进入到本科学习,专科和本科都可以考研成为研究生...

在这里, 学历就是状态,而对应的变量可以是成绩或者说个人的努力

适用场景:

  1. 存在多个状态
  2. 状态之间有固定的转化逻辑

代码结构

stateMode.png

状态接口

一个未实现的抽象的的业务方法

Context上下文类(维护状态接口)

通过策略模式来调用状态类

内部维护了一个状态接口的成员对象,提供初始化以及修改状态的方法

一个客户端调用方法,用于间接调用状态接口的方法

具体状态类(实现状态接口)

完成当前状态的业务代码

其中可能会涉及状态修改,因此需要修改上下文类的属性。

可通过成员对象或者业务方法参数的方法传递上下文类,通过上下文类来修改状态

具体代码

为方便理解,这里根据前面的学历例子,结合代码结构进行代码展示

状态接口

/**
 * 对应state接口
 * 学历
 */
public interface EducationBackground {
    // 在对应的学历中学习
    public void study(Person person);
}

Context上下文类

**
 * 上下文类 -> Person
 */
public class Person {
    String name;
    // 影响状态变量 -> 影响学历的分数
    Integer score;
    // 状态接口 -> 学历接口
    EducationBackground educationBackground;

    public Person(String name) {
        this.name = name;
        this.educationBackground = new HighSchool();
    }

    public void setEducationBackground(EducationBackground educationBackground) {
        this.educationBackground = educationBackground;
    }

    public void study() {
        // 间接调用,同时传递上下文类
        educationBackground.study(this);
    }
}

具体状态类

高中类

public class HighSchool implements EducationBackground{
    @Override
    public void study(Person person) {
        System.out.println(person.name + "高中学习中,取得成绩 "+ person.score);
        if(person.score>=60 && person.score<80){
            person.setEducationBackground(new JuniorCollege());
        }else if(person.score>=80){
            person.setEducationBackground(new Undergraduate());
        }
    }
}

专科类

public class JuniorCollege implements EducationBackground{
    @Override
    public void study(Person person) {
        System.out.println(person.name + "专科学习中,取得成绩 "+ person.score);
        if(person.score>=90 && person.score < 95){
            person.setEducationBackground(new Undergraduate());
        }else if( person.score >= 95){
            person.setEducationBackground(new Graduate());
        }
    }
}

本科类

public class Undergraduate implements EducationBackground{
    @Override
    public void study(Person person) {
        System.out.println(person.name + "本科学习中,取得成绩 "+ person.score);
        if(person.score>=90){
            person.setEducationBackground(new Graduate());
        }
    }
}

研究生类

public class Graduate implements EducationBackground{
    @Override
    public void study(Person person) {
        System.out.println(person.name + "研究生学习中");
    }
}

调用

public static void main(String[] args) {
    Person ming = new Person("ming");
    ming.score = 70;
    ming.study();
    ming.score = 92;
    ming.study();
    ming.score = 95;
    ming.study();

    ming.study();
}

image.png

与策略模式的关系

状态模式本质是一种扩展的策略模式

从代码结构来看,上下文类与状态类的关系与策略类完全一致,策略模式的策略类等同于状态模式的状态类

但不同点是,策略类之间是独立的,无关联的,而状态之间的关联的

状态模式的优点

  1. 符合开放-封闭原则,当出现新的状态,只需新建状态类解决
  2. 调用方无需关注具体的状态改变,降低耦合

思维导图

image.png

部分图片来源: refactoringguru.cn/design-patt…