35. 状态模式

定义

状态模式(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();
    }
}
//不在状态
//在状态

现在状态有专门的维护,而且状态也可以在外部去改变,不管是喝脉动还是可口可乐,都能让这种状态进行变动,而且如果要加状态,就只需要加类就可以了,通过增加类的方式,我们实现了状态模式。

优点

  1. 封装转换过程;
  2. 聚合了状态对象,操作委托给子类,简化代码。

缺点

  1. 一个状态就是一个类,类真™的多。

应用场景

  1. 状态很重要,行为取决于状态的;
  2. 操作中有多分支语句,而且分支依赖状态。

程序

e35_state_pattern

吐槽

还是会用枚举来表示状态,数据库存一个int类型表示不同的状态,对象?对数据库太不友好了。

https://www.jianshu.com/p/0b9f16d360cf

你可能感兴趣的:(35. 状态模式)