Java设计模式百例 - 状态模式

本文源码见:https://github.com/get-set/get-designpatterns/tree/master/state

在状态模式(State Pattern)中,类的行为是基于它的状态改变的。这种类型的设计模式属于行为型模式。

我们程序猿在码代码的时候由于不同的工作状态,可能写出质量不一的代码,并我们不是AI嘛。

  • 早上上班的时候,休息了一夜,精力旺盛,程序猿能够高效码代码,bug也不多;
  • 当熬夜加班的时候,运转了一天的大脑无比疲惫,写出的代码常有bug出没;
  • 当然,我们也都非常期待在码代码的时候能够达到“天人合一”之境界(虽然这种状态通常出现在玩游戏时),没有烦人的会议、没有别人的打扰,虽然没有程序猿鼓励妹子在侧,却能几分钟写出通常需要几个小时才能写出的逻辑,解决近几天都未解决的问题,可谓“码神附体”!

例子

如果上述情况用代码来表述的话,我们来设计一下。

程序猿还是同一个人,但是同一个任务在不同的状态下,可能会达到不同的效果。

注意上边这句话,有两个“同一个”和两个”不同的“。

人和任务是相同的,是不变的部分;状态和效果是不同的,是变的部分。按照设计模式的套路,不变的和变化的是要分开来的,从而满足”开闭“原则,有利于扩展。

不变的是人(类Developer)和任务(方法Developer.develop()),变化的状态(类XxxState)作为Developer的成员变量能够随时切换看来就可以解决这个问题。

由于状态是变化的,因此需要不同的类XxxState来描述,其方法XxxState.develop()正好可以灵活实现不同状态下的工作效果。

完美!最后还有一个,按照设计模式的通常套路,同一类变化的类要抽象为接口或抽象类,并提供统一的接口方法,从而做到”面向接口“编程,以应对变化。

设计完毕,那就开工:

Developer.java

public class Developer {
    private State state;

    public Developer(State state) {
        this.state = state;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void develop() {
        state.coding();
    }
}

Developer维护有State的引用,并提供setState(State)方法切换状态。

State.java

public interface State {
    void coding();
}

EffectiveState.java

public class EffectiveState implements State {
    public void coding() {
        System.out.println("高效码代码,偶有bug,人非圣贤嘛~");
    }
}

ExhaustedState.java

public class ExhaustedState implements State {
    public void coding() {
        System.out.println("加班熬夜码代码,专业写bug");
    }
}

TianRenHeYiState.java

public class TianRenHeYiState implements State {
    public void coding() {
        System.out.println("写代码进入天人合一境界,仿佛三头六臂,码神附体");
    }
}
状态类的抽象

不同的状态有不同的实现效果,通过State抽象出统一的接口。

测试一下:

Client.java

public class Client {
    public static void main(String[] args) {
        Developer developer = new Developer(new EffectiveState());
        developer.develop();
        developer.setState(new ExhaustedState());
        developer.develop();
        developer.setState(new TianRenHeYiState());
        developer.develop();
    }
}

使用DevelopersetState方法切换不同的状态,从而实现不同的操作:

高效码代码,偶有bug,人非圣贤嘛~
加班熬夜码代码,专业写bug
写代码进入天人合一境界,仿佛三头六臂,码神附体

总结

这就是状态模式,将不同的状态包装为不同的类,供其本体引用,从而实现灵活的状态切换。

看到这里其实感觉状态模式和策略模式很像,状态模式是将不同的状态对象作为成员变量给使用者(也称”环境“),策略模式是将不同的策略对象作为成员变量给使用者(也称”环境“)。其实二者还是有些使用上的区别的:

  • 策略模式中,作为成员变量的策略对象通常不会经常变化;而状态模式在使用者(也称”环境“)的整个生命周期中会不断变化。
  • 策略模式中,通常并不明确告诉客户端所选择的具体策略;而状态模式中,所处的状态是明确告知客户端的;
  • 通常策略模式的使用者自己选择一个具体策略;而状态模式的使用者(也称”环境“)通常是被动使用某种状态。

使用场景

  • 一个对象的行为依赖于它所处的状态,对象的行为必须随着其状态的改变而改变;
  • 对象在某个方法里依赖一重或多重的条件转移语句,而且其中有大量代码的时候。

注意事项

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,162评论 25 707
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,639评论 18 399
  • 原文链接:http://blog.csdn.net/zhangerqing http://www.cnblogs....
    孤独杂货铺阅读 1,516评论 0 3
  • 小鱼和小姐妹包子得了几张免费拍婚纱照的券,一听免费便心动了,小鱼叫上老公,包子本也想叫老公一起去,但包子老公是个十...
    小含歌阅读 464评论 3 2
  • 当激情散去,我们依然前行,成功之路才刚刚显现…… 路上一定会经历挫折磨难,但挫折磨难一定是我们灵魂与事业升起的层层...
    国仕空间阅读 261评论 0 0