定义
状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。其别名为状态对象(Objects for States)。
通俗理解
“感觉不在状态,随时脉动回来!”,这个广告词随着脉动的广告铺天盖地地袭来,本来要扔飞机给心怡女生却扔给一个肌肉男的年轻男子、在图书馆不在状态把一排书给碰掉的大学生,在喝了脉动以后,都恢复了状态。用彩色的球球弹钢琴,潇洒地走掉不管那排倒了的书。
在脉动广告里面有两种状态,一种是“在状态”,一种是“不在状态”,那么这种状态,是我们人里面的基本属性、还是外在属性?基本属性的含义是,人生来就有的,不需要外部去培养,不需要使用外界的眼光去判断的或者是有明确标准的。而外在属相就是,需要后台去培养,而且需要的眼光去判断并且没有明确标准的。这个有点绕,举个例子,例如我们的身高体重,不管我们怎么去看,我们的身高是1.7m就是1.7m,换个度量衡说8尺也行,就这个就是基本的属性,不需要使用外界的眼光去判断,有明确标准。那外在的属性呢?例如我们对某个孩子的评价,我们说,某个孩子很调皮,经常拆坏家里的电气。但是,调皮这个评价是孩子的内在评价么?我看不,我们也可以说这个孩子很有创造力。这样有不同标准的属性就是外在的属性。
那么,“在状态”和“不在状态”,是什么属性?显然是外在的,我们可以去评价那个扔错飞机的人是一个“在状态的”,或许他就是想扔飞机给肌肉男,而用扔给女生作为一个接口。同时,我们也可以说他是不在状态的。
具体表现在程序上,就是状态的属性,我们是使用基本类型(String也算是基本类型)去维护还是使用对象去维护。而状态模式的精髓,就在于我们使用一个对象类型去维护状态,而且这个对象还要是一个抽象类。
示例
业务按脉动来定义。
渣渣程序
人
public class Human {
private String state;
public Human(String state) {
this.state = state;
}
public void drinkMaidong() {
if("不在状态".equals(state)) {
System.out.println("喝脉动");
this.state = "在状态";
} else {
System.out.println("已经在状态了,不要再喝了");
}
}
public void run() {
if("在状态".equals(state)) {
System.out.println("跑步");
this.state = "不在状态";
} else {
System.out.println("不喝脉动就跑步,不行呀");
}
}
public void checkState() {
System.out.println(this.state);
}
}
程序入口
public class Main {
static Human human = new Human("不在状态");
public static void main(String[] args) {
human.run();
human.checkState();
human.drinkMaidong();
human.checkState();
}
}
//不喝脉动就跑步,不行呀
//不在状态
//喝脉动
//在状态
好了,现在这代码出现了,不喝脉动就跑步,不行呀
的情况,这明显不行哩,个人是判断不了自己在不在状态的,而且,如果我如果要加一个平时状态
的话,我还得去改相关的代码,这是不合理的。问题就出在,我维护了状态,同时也维护了状态的改变。那么只需要把状态的改变提取到方法外面来,就可以了。
优化
类图
代码
状态接口以及实现
public abstract class State {
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public void checkState() {
System.out.println(state);
}
}
public class TiredState extends State {
static class SingletonHonlder {
static TiredState tiredState = new TiredState();
}
public static TiredState getTiredState() {
return SingletonHonlder.tiredState;
}
private TiredState() {
this.setState("不在状态");
}
}
//WakeUpState类似
人
public class Human {
private State state;
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void checkState() {
this.state.checkState();
}
}
程序入口
public class Main {
static Human human = new Human();
public static void main(String[] args) {
human.setState(TiredState.getTiredState());
human.checkState();
human.setState(WakeUpState.getTiredState());
human.checkState();
}
}
//不在状态
//在状态
现在状态有专门的维护,而且状态也可以在外部去改变,不管是喝脉动还是可口可乐,都能让这种状态进行变动,而且如果要加状态,就只需要加类就可以了,通过增加类
的方式,我们实现了状态模式。
优点
- 封装转换过程;
- 聚合了状态对象,操作委托给子类,简化代码。
缺点
- 一个状态就是一个类,类真™的多。
应用场景
- 状态很重要,行为取决于状态的;
- 操作中有多分支语句,而且分支依赖状态。
程序
吐槽
还是会用枚举来表示状态,数据库存一个int类型表示不同的状态,对象?对数据库太不友好了。