设计模式-状态模式
既然谈到状态模式,那么我们就很有必要探讨一个问题
什么是状态?
具体到代码中,就是对象内部的变量处于的阶段,所谓阶段是由具体业务定义的。
现实例子
我们就以大多数人都经过的学历为例子
stateDiagram-v2
高中 --> 专科
高中 --> 本科
专科 --> 本科
本科 --> 研究生
专科 --> 研究生
高考结束了,有的同学通过高考进入了专科学习,有些同学进入了本科学习,也有些同学选择复读仍在高中学习......
专科学习的同学通过专升本可以进入到本科学习,专科和本科都可以考研成为研究生...
在这里, 学历就是状态,而对应的变量可以是成绩或者说个人的努力
适用场景:
- 存在多个状态
- 状态之间有固定的转化逻辑
代码结构
状态接口
一个未实现的抽象的的业务方法
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();
}
与策略模式的关系
状态模式本质是一种扩展的策略模式
从代码结构来看,上下文类与状态类的关系与策略类完全一致,策略模式的策略类等同于状态模式的状态类
但不同点是,策略类之间是独立的,无关联的,而状态之间的关联的
状态模式的优点
- 符合开放-封闭原则,当出现新的状态,只需新建状态类解决
- 调用方无需关注具体的状态改变,降低耦合
思维导图
部分图片来源: refactoringguru.cn/design-patt…