行为型模式:状态模式

十一大行为型模式之八:状态模式。

简介

姓名 :状态模式
英文名 :State Pattern
价值观 :有啥事让状态我来维护
个人介绍
Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.
当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
(来自《设计模式之禅》)

你要的故事

现在有好多个人贷款软件,比如:支付宝、360借条(打广告。。。)等等。贷款会有一个用户状态流程,游客->注册用户->授信用户->借款用户(这里简化了状态,只用 4 个)。每个状态拥有的权限不一样,如下图所示。

从上图可以看到,一个用户有 3 种行为,分别是注册、授信、借款。当注册成功后,用户的状态就从『游客』改变为『注册用户』;当授信成功后,用户的状态就从『注册用户』改变为『授信用户』;当借款成功后,用户的状态就从『授信用户』改变为『借款用户』。现在我们就来实现用户注册、授信、借款的过程,因为每个状态的权限不一样,所以这里需要根据用户的状态来限制用户行为。

很快,我们就完成下面的代码。

class User {
    private String state;

    public String getState() {
        return state;
    }

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

    public void register() {
        if ("none".equals(state)) {
            System.out.println("游客。注册中。。。");
        }else if ("register".equals(state)) {
            System.out.println("注册用户。不需要再注册。");
        } else if ("apply".equals(state)) {
            System.out.println("授信用户。不需要再注册。");
        } else if ("draw".equals(state)) {
            System.out.println("借款用户。不需要再注册。");
        }
    }

    public void apply() {
        if ("none".equals(state)) {
            System.out.println("游客。不能申请授信。");
        }else if ("register".equals(state)) {
            System.out.println("注册用户。授信申请中。。。");
        } else if ("apply".equals(state)) {
            System.out.println("授信用户。不需要再授信。");
        } else if ("draw".equals(state)) {
            System.out.println("借款用户。不需要再授信。");
        }
    }

    public void draw(double money) {
        if ("none".equals(state)) {
            System.out.println("游客。申请借款【" + money + "】元。不能申请借款。");
        } else if ("register".equals(state)) {
            System.out.println("注册用户。申请借款【" + money + "】元。还没授信,不能借款。");
        } else if ("apply".equals(state)) {
            System.out.println("授信用户。申请借款【" + money + "】元。申请借款中。。。");
        } else if ("draw".equals(state)) {
            System.out.println("授信用户。申请借款【" + money + "】元。申请借款中。。。");
        }
    }
}

public class NoStateTest {

    public static void main(String[] args) {
        User user = new User();
        user.setState("register");
        user.draw(1000);
    }

}

打印结果:
注册用户。申请借款【1000.0】元。还没授信,不能借款。

上面代码实现了用户 register (注册),apply (授信),draw (借款) 这 3 种行为,每个行为都会根据状态 state 来做权限控制。看起来有点繁琐,扩展性不高,假设新增了一个状态,那么注册、授信、借款这 3 种行为的代码都要修改。下面通过状态模式来解决这个问题。

我们把状态给抽出来,作为一个接口,因为在每种状态中都可能有注册、授信、借款行为,所以把这 3 个行为作为状态接口的方法,让每个状态子类都实现相应的行为控制。如下代码所示。

interface State {

    void register();

    void apply();

    void draw(double money);
}

/**
 * 游客
 */
class NoneState implements State {

    @Override
    public void register() {
        System.out.println("游客。注册中。。。");
    }

    @Override
    public void apply() {
        System.out.println("游客。不能申请授信。");
    }

    @Override
    public void draw(double money) {
        System.out.println("游客。申请借款【" + money + "】元。不能申请借款。");
    }
}

/**
 * 注册状态
 */
class RegisterState implements State {

    @Override
    public void register() {
        System.out.println("注册用户。不需要再注册。");
    }

    @Override
    public void apply() {
        System.out.println("注册用户。授信申请中。。。");
    }

    @Override
    public void draw(double money) {
        System.out.println("注册用户。申请借款【" + money + "】元。还没授信,不能借款。");
    }
}

/**
 * 授信状态
 */
class ApplyState implements State {

    @Override
    public void register() {
        System.out.println("授信用户。不需要再注册。");
    }

    @Override
    public void apply() {
        System.out.println("授信用户。不需要再授信。");
    }

    @Override
    public void draw(double money) {
        System.out.println("授信用户。申请借款【" + money + "】元。申请借款中。。。");
    }
}

/**
 * 借款状态
 */
class DrawState implements State {

    @Override
    public void register() {
        System.out.println("借款用户。不需要再注册。");
    }

    @Override
    public void apply() {
        System.out.println("借款用户。不需要再授信。");
    }

    @Override
    public void draw(double money) {
        System.out.println("申请借款【" + money + "】元。申请借款中。。。");
    }
}

class User1 {
    private State state;

    public State getState() {
        return state;
    }

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

    public void register() {
        this.state.register();
    }

    public void apply() {
        this.state.apply();
    }

    public void draw(double money) {
        this.state.draw(money);
    }
}

public class StateTest {
    public static void main(String[] args) {
        User1 user1 = new User1();
        user1.setState(new RegisterState());
        user1.apply();
        user1.draw(1000);
        user1.setState(new ApplyState());
        user1.draw(2000);
    }

}

打印结果:
注册用户。授信申请中。。。
注册用户。申请借款【1000.0】元。还没授信,不能借款。
授信用户。申请借款【2000.0】元。申请借款中。。。

看上面代码,我们抽象了 State 接口,4 种状态分别用 NoneState (游客)、RegisterState (注册)、ApplyState (授信)、DrawState (借款) 表示。而每个状态都有 3 种行为,它们各自对这些行为进行权限控制。这样子实现可以让权限逻辑分离开,分散到每个状态里面去,如果以后要业务扩展,要新增状态,那就很方便了,只需要再实现一个状态类就可以,不会影响到其他代码。这也是为什么《阿里巴巴 Java 开发手册》里面讲的,当超过 3 层的 if-else 的逻辑判断代码,推荐用状态模式来重构代码。

总结

状态模式 很好的减低了代码的复杂性,从而提高了系统的可维护性。在业务开发中可以尝试使用,比如在迭代开发中,业务逻辑越来越复杂,从而不得不使用很多 if-else 语句来实现时,就可以考虑一下是不是可以用 状态模式 来重构,特别是一些有状态流程转换方面的业务。看到这篇文章,想想工作中是不是有些复杂的代码可以重构,赶紧行动起来。

推荐阅读:

行为型模式:观察者模式

行为型模式:迭代器模式

行为型模式:策略模式

设计模式系列文章持续更新中,欢迎关注公众号 LieBrother,一起交流学习。

(0)

相关推荐

  • 设计模式(二十二)——状态模式(APP抽奖活动+借贷平台源码剖析)

    24.1 APP 抽奖活动问题 请编写程序完成 APP 抽奖活动 具体要求如下: 1) 假如每参加一次这个活动要扣除用户 50 积分,中奖概率是 10% 2) 奖品数量固定,抽完就不能抽奖 3) 活动 ...

  • 状态模式

    一.状态模式介绍 1.定义与类型 允许一个对象在其内部状态改变时,改变它的行为 类型:行为型 2.适用场景 一个对象存在多个状态(不同状态下行为不同),且状态可相互转换 3.优点 将不同的状态隔离 把 ...

  • JAVA中equals的用法

    Object类中的equals方法用于检测一个对象是否等于另一个对象.在Object类中,这个方法判断两个对象是否具有相同的引用,如果两个对象具有相同的引用,它们一定是相等的.从这点上看,将其作为默认 ...

  • 简说设计模式——状态模式

    一.什么是状态模式 状态这个词汇我们并不陌生,在日常生活中,不同时间就有不同的状态,早上起来精神饱满,中文想睡觉,下午又渐渐恢复,晚上可能精神更旺也可能耗费体力只想睡觉,这一天中就对应着不同的状态.或 ...

  • 吊打面试官系列:说说hashCode和equals方法

    首先我们需要知道hashCode方法和equals方法都是属于Object类的方法.既然属于Object中public修饰的方法,那言外之就是所有对象默认都有这两个方法,只是有时候有的对象已对这两个方 ...

  • 设计模式-行为型-状态模式

    状态模式(State): 在软件开发过程中,应用程序可能会根据不同的情况作出不同的处理.最直接的解决方案是将这些所有可能发生的情况全都考虑到,然后使用if else语句来做状态判断来进行不同情况的处理 ...

  • PHP设计模式之状态模式

    PHP设计模式之状态模式 状态模式从字面上其实并不是很好理解.这里的状态是什么意思呢?保存状态?那不就是备忘录模式了.其实,这里的状态是类的状态,通过改变类的某个状态,让这个类感觉像是换了一个类一样. ...

  • [PHP小课堂]PHP设计模式之状态模式

    [PHP小课堂]PHP设计模式之状态模式 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[DarkMatterZyCoder/149844827]免费得PHP.项目管理学习资料

  • 自主互助学习型课堂教学模式学习心得

    学校大力提倡自主.互助.学习型课堂应该已很长时间了.作为新进教师,通过对这份材料的学习我感觉获益匪浅,也在一定程度上加深了我对课堂教学的认知.下面浅谈几句我在自主.互助学习型课堂材料中的点滴学习体会. ...

  • 刘昌俊委员:调整临床医学学术型研究生培养模式

    临床医学科学学位研究生教育是我国培养科研型医学人才的主要方式.自临床医学学术型研究生培养方式建立以来,在高级.研究型医学人才培养方面取得突出成绩,为我国医学事业发展做出了重要贡献. 当前,我国学术型研 ...

  • 三步四环节五课型课堂教学模式

    一."三+四+五优质高效课堂"的总体构架 "三+四+五优质高效课堂"中的三四五是指"三步四环节五课型". 1.三步: 是指"课前预 ...

  • 无废话设计模式(16)行为型模式--备忘录模式

    0-前言 备忘录模式定义:在不破坏封装的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态. 这样以后就可以将该对象恢复到原先保存的状态. 1-实现 备忘录模式设计的初衷是用于备份状态. 但是 ...