随时灵活变化-状态模式

作者: 黑色小老虎丶 | 来源:发表于2017-11-14 18:10 被阅读53次

模式介绍

状态模式的结构和策略模式几乎一模一样。

但是它们两者的目的、本质却完全不同。

策略模式的行为是彼此独立,相互替换的。回想之前举的价格计算器,我们出行时想使用地铁,则使用地铁的价格计算器,如果使用出租车,则使用出租车的价格计算器......

状态模式的行为则是平行的,不可替换的。状态模式更像是被封装在对象内部的一个东西,当对象的状态发生变化时,其行为也要发生变化。

使用场景

  • 一个对象的行为需要根据状态发生变化,尤其是在运行时状态发生变化,行为需要跟着一起变化时;
  • 代码中有大量判断语句(if、switch),且这些语句依赖该对象的状态。

模式角色

  • State:状态接口,定义所有行为的抽象。
  • ConcreteStateA、ConcreteStateB:某个状态的具体行为实现,一个状态对应一个具体行为实现。

模式示例

相信大家在开发中,只要是动态App(和服务器有交互),都会有登录的需求。

针对这个需求,我们可以得出两个状态:登录状态、未登录状态。

接着我们可以想象一些行为:

  • 登录
  • 退出登录
  • 查看账户金币
  • 赚取金币
  • 金币兑换道具

针对上述行为,在登录状态和未登录状态下,所做的事情是完全不同的:

  1. 登录状态:
    • 登录:提示用户已经登录过了,请勿重复登录
    • 退出登录:清除用户缓存并提示用户退出登录成功
    • 查看账户金币:从服务器查询用户余额
    • 赚取金币:跳转到赚金币页面
    • 金币兑换道具:跳转到兑换道具页
  2. 未登录状态:
    • 登录:判断用户输入的账号密码,正确提示用户登录成功。
    • 退出登录:提示用户已经退出过了。
    • 查看账户金币:提示用户请先登录
    • 赚取金币:跳转到赚金币页(这里也可以提示用户登录,具体看产品定的登录时机)
    • 金币兑换道具:提示用户请先登录

想必看完这个示例,大家已经对状态模式有了一些自己的见解。

这种情况下,非常适合使用状态模式

如果项目中,还是通过判断语句来进行状态的区分,就说明这个项目没有很好地应用状态模式

下面我们就来将上述案例转化成代码。

首先是状态行为的抽象,该抽象包含了所有的行为:

public interface UserState {

    //登录
    void login();

    //登出
    void logout();

    //查询余额
    void seeMoney();

    //赚金币
    void earnMoney();

    //兑换道具
    void exchange();
}

针对我们上面描述的示例,有以上5种行为,我们将其进行了抽象。

接着来思考行为的具体实现:登录状态的具体实现、未登录状态的具体实现。

具体做起来也很简单,就是创建两个类去实现我们的行为抽象,在各自的实现下,去实现该状态下,应该做的事情。

首先来看登录状态:

public class LoginStateImpl implements UserState {
    @Override
    public void login() {
        Toast.makeText(App.context, "您已经登录了,无需登录!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void logout() {

        Toast.makeText(App.context, "退出登录成功!", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void seeMoney() {
        Toast.makeText(App.context, "您目前有100金币", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void earnMoney() {
        Toast.makeText(App.context, "跳转到-赚金币", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void exchange() {
        Toast.makeText(App.context, "跳转到-兑换道具", Toast.LENGTH_SHORT).show();
    }
}

根据示例需求,我实现了登录状态下,这5种行为的具体实现。

未登录状态也是同理,这里就不列举代码了,可以直接查看GitHub

接下来我们来看一下测试代码:

//默认是未登录状态
private UserState userState = new LogutStateImpl();

@Override
public void onClick(View view) {
    switch (view.getId()) {
        case R.id.bt_login://登录行为
            userState.login();
            //核心:更换用户状态
            userState = new LoginStateImpl();
            break;
        case R.id.bt_logout://退出登录行为
            userState.logout();
            userState = new LogutStateImpl();
            break;
        case R.id.bt_see_money://查看余额行为
            userState.seeMoney();
            break;
        case R.id.bt_earn_money://赚取金币行为
            userState.earnMoney();
            break;
        case R.id.bt_exchange://兑换行为
            userState.exchange();
            break;
    }
}

这里也是利用多态的特性,根据状态的变化,注入不同的实现。

至此,我们已经使用状态模式成功实现了上述需求,并且去除了重复、杂乱的判断语句,体现出了状态模式的精髓。

总结

代码已经上传至GitHub,可以下载查阅。

其实看到这里,各位看官想必已经了解了状态模式。

状态模式的关键点在于:不同状态下、同一行为的不同响应。

状态模式是为了优化代码结构而产生的。我们通过if-else其实可以完美判断用户的登录状态,但是这种实现使得逻辑与具体行为耦合在一起,后期难以维护。

状态模式就是为了消除这种丑态,实现逻辑与行为的解耦。

当然并不是所有的if-else都适合使用状态模式,具体是否使用,还是由你来决定。

相关文章

  • 随时灵活变化-状态模式

    模式介绍 状态模式的结构和策略模式几乎一模一样。 但是它们两者的目的、本质却完全不同。 策略模式的行为是彼此独立,...

  • 状态变化模式

    在组件构建过程中,某些对象的状态经常面临变化,如何对这些变化进行有效的管理?同时又维持高层模块的稳定?“状态变化”...

  • Boolan 第十三周 设计模式(三)

    状态变化模式 典型模式 State Memento 1 state目的是应对对象状态变化,行为也要随之变化,保持对...

  • Android设计模式之(7)----状态模式

    状态模式 所谓状态模式,就是代表一个事物有多个状态。因为状态的变化而导致一系列的变化。 听起来和策略模式很相似,都...

  • 状态模式

    状态模式属于状态变化模式。由一个状态维持类来控制当前的状态,把不同的状态写成不同的派生类,当状态发生变化时,状态维...

  • JS设计模式之状态模式

    # 什么是“状态模式”? 状态模式:对象行为是根据状态改变,而改变的。特点:正是由于内部状态的变化,导致对外的行为...

  • Corona灯光+材质小结

    一、第一阶段学习心得 1.CR灯光很酷炫,操作比vr方便,快捷, 2.交互模式,渲染很灵活,可是随时实用,也能随时...

  • 状态设计和场景切换

    状态设计模式,即某个角色有多种状态,需要在各个状态切换时,使用这种状态设计使代码更加灵活,简化了代码的判断逻辑,主...

  • lxidea的 Boolan C++设计模式 学习笔记(三)

    本周的设计模式比较多了,主要分为“对象性能”模式,“状态变化”模式, 对象性能模式 Singleton单件模式 保...

  • 设计模式之观察者模式

    前言 观察者模式,即为观察对象的变化,并能够随时得到对象变化的通知。此类模式我们在平时开发中所见的也比较多,例如我...

网友评论

    本文标题:随时灵活变化-状态模式

    本文链接:https://www.haomeiwen.com/subject/qgvfvxtx.html