Android开发经验谈Android开发Android知识

随时灵活变化-状态模式

2017-11-14  本文已影响53人  黑色小老虎丶

模式介绍

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

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

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

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

使用场景

模式角色

模式示例

相信大家在开发中,只要是动态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都适合使用状态模式,具体是否使用,还是由你来决定。

上一篇 下一篇

猜你喜欢

热点阅读