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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350