Android 设计模式之状态模式

在日常开发过程中时常需要用到设计模式,但是设计模式有23种,如何将这些设计模式了然于胸并且能在实际开发过程中应用得得心应手呢?和我一起跟着《Android源码设计模式解析与实战》一书边学边应用吧!

设计模式系列文章

今天我们要讲的是状态模式(State模式)


定义

当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类

使用场景

  • 一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为
  • 代码中包含大量与对象状态有关的条件语句,例如,一个操作中含有庞大的多分支语句(if-else或switch-case),且这些分支依赖于该对象的状态

使用例子

  • 最常见的应用是用户登录系统

实现

3大角色

  • 环境类:定义客户端感兴趣的接口,维护一个抽象状态类的子类的实例,这个实例定义了对象当前状态
  • 抽象状态类或状态接口:定义一个或一组接口,表示该状态下的行为
  • 具体状态类:每个具体状态类实现抽象状态类中定义的接口,从而达到不同状态下的不同行为

实现的要点

  • 把不同状态下的行为抽象成共同的接口到抽象状态类中
  • 根据不同的状态,具体的状态类实现抽象状态类中的接口,从而实现不同的行为
  • 环境类,也就是对外提供服务的类通过依赖抽象状态类来实现具体的行为,同时也达到与具体状态类的解耦

实现方式

下面我们以日常开发中的登录功能来简单应用下状态模式

  • 在登录模块中一般我们会根据用户是否登录状态而有不同的操作,这里简单模拟2个操作,转发和评论
public interface UserState {

    /**
     * 转发
     *
     * @param context
     */
    public void forward(Context context);

    /**
     * 评论
     *
     * @param context
     */
    public void comment(Context context);
}
  • 登录状态,调用转发和评论直接简单地弹出个Toast
public class LoginedState implements UserState {

    @Override
    public void forward(Context context) {
        Toast.makeText(context, "转发成功", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void comment(Context context) {
        Toast.makeText(context, "评论成功", Toast.LENGTH_SHORT).show();

    }
}
  • 未登录状态,调用转发和评论跳转到登录页面,这里直接简单地弹出登录的提示
public class LogoutState implements UserState {

    @Override
    public void forward(Context context) {
        Toast.makeText(context, "未登录,跳转到登录页面", Toast.LENGTH_SHORT).show();

    }

    @Override
    public void comment(Context context) {
        Toast.makeText(context, "未登录,跳转到登录页面", Toast.LENGTH_SHORT).show();

    }
}

  • 根据不同的状态表现不一样的行为。下面我们看看对外提供服务的环境类
public class LoginContext {

    /**
     * 用户状态,默认为登录状态
     */
    UserState userState = new LoginedState();

    /**
     * 单例
     */
    static LoginContext loginContext = new LoginContext();

    private LoginContext() {

    }

    public LoginContext getLoginContext() {
        return loginContext;
    }

    public void setUserState(UserState userState) {
        this.userState = userState;
    }

    public void forward(Context context) {
        userState.forward(context);
    }

    public void comment(Context context) {
        userState.comment(context);
    }
}

  • 以上的环境类的实现中,默认状态设置为登录状态,这个可以根据实际需要来定。下面我们看看怎么调用
//因为默认是登录状态,所以可以直接调用转发功能
LoginContext.getLoginContext().forward(MainActivity.this)

//注销登录,也就是登录状态改为未登录
LoginContext.getLoginContext().setUserState(new LogoutState());

//注销登录了以后再调用转发或是评论功能,执行的就会是弹出登录提示
LoginContext.getLoginContext().forward(MainActivity.this)
  • 通过以上的例子我们就简单地实现了状态模式的应用啦

通过上面的例子我们可以看出,状态模式把对象的不同状态下的行为封装起来,并与对象的状态联系在一起。对象的状态改变了,对象的行为也会改变。在上面的例子中就是登录的状态LoginContext中的UserState状态不一样,执行的行为,比如转发功能就不一样

状态模式和策略模式

状态模式和策略模式的结构几乎完全一样,但它们的目的、本质却完全不一样。状态模式的行为是平行的、不可替换的,策略模式的行为是彼此独立、可相互替换的。用一句话来表述,状态模式把对象的行为包装在不同的状态对象里,每一个状态对象都有一个共同的抽象状态基类。状态模式的意图是让一个对象在其内部状态发生改变的时候,其行为也随之改变

总结

  • 状态模式的关键点在于不同的状态下对于同一行为有不同的响应,这其实就是一个将if-else用多态来实现的具体实例
  • 状态模式将所有与一个特定状态相关的行为都放入一个状态对象中,它提供了一个更好的方法来组织与特定状态相关的代码,将繁琐的状态判断转换成结构清晰的状态类族,在避免代码膨胀的同时也保证了可扩展性和可维护性

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,442评论 25 707
  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,897评论 1 15
  • 本文首发于个人博客:Lam's Blog - 谈谈23种设计模式在Android源码及项目中的应用,文章由Mark...
    格子林ll阅读 4,619评论 1 105
  • 亲爱的DD:你好! 每天晚上睡觉前,都是妈妈给你讲绘本故事的快乐时光。最近,你最喜欢的绘本是《小猪佩奇》,一套共有...
    Leice阅读 174评论 0 0
  • 什么时候呢 开始为了生活而生活 为了工作而工作 恐惧 将就 妥协 忙忙碌碌却碌碌无为 生活成了一部默声的黑白影片 ...
    记忆之城SINCE1994阅读 290评论 0 0