设计模式之状态模式

栏目: 后端 · 发布时间: 5年前

内容简介:你是否经常请(】。在这不同的状态是可以有不同的操作的。

一、定义

你是否经常请( )假( )?是不是对公司万恶的请假申请流程深 痛绝 。有没有想过偷偷改造这个万恶的系统,从 申请->项目经理审批->部门审批->老板审批->完成  偷偷改为  申请->完成。为了实现这个正义[ 偷笑 ]又合理的诉求,你得先学会今天要介绍的设计模式,因为你们公司的这个流程可能就是用今天这个模式设计的。来看看这个 设计模式 是怎么来抽象这类流程性的业务的。

状态模式【百度百科】 :当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。

这个定义看起来莫名其妙,咋一看,我也不知道它要表达什么。个人的理解:某个对象是有状态的,比如我们上面的请假流程,它处于项目经理状态,那项目经理可以审核你的请假申请,到了老板处理环节,老板直接把你申请单删了【 哈哈

】。在这不同的状态是可以有不同的操作的。

不知道你看懂了定义了没??什么?没看懂,那就直接看下面的代码咯,talk is cheap show me the code。

二、UML图

UML图如下,我直接把请假这个例子画了个UML图,如下,有一个 公共的State抽象类 ,里面定义了两个变量来保存当前状态的状态Code,状态Name,下面为 具体的状态 ,分别为:AppState(申请状态),ProjectManagesState(项目经理审核状态),BossState(老板审核状态),通过Context来提供给客户端使用。

设计模式之状态模式

三、请假流程实现

具体代码实现如下:

1、状态抽象类

package com.design.state;

public abstract class State {

    private String stateCode;
    private String stateName;
    //往下个环节走
    public abstract void toNextState(Context context);

    public State(String stateCode, String stateName){
        this.stateCode = stateCode;
        this.stateName = stateName;
    }

    public String getStateCode() {
        return stateCode;
    }

    public void setStateCode(String stateCode) {
        this.stateCode = stateCode;
    }

    public String getStateName() {
        return stateName;
    }

    public void setStateName(String stateName) {
        this.stateName = stateName;
    }
}
复制代码

2、定义具体的状态

package com.design.state;

/**
 * 申请状态
 */
public class AppState extends State{

    public AppState(){
        super("Apply", "申请环节");
    }

    @Override
    public void toNextState(Context context) {
        //申请状态,这里可以做该状态下的操作
        System.out.println("我是申请人,我申请休假,下一个环节是项目经理审核!!");
        //直接进去项目经理审核状态
        context.setCurrentState(new ProjectManagesState());
    }
}
复制代码
package com.design.state;

/**
 * 项目经理审核状态
 */
public class ProjectManagesState extends State{

    public ProjectManagesState(){
        super("ProjectManages", "项目经理审核环节");
    }
    @Override
    public void toNextState(Context context) {
        //项目经理审核状态,这里可以做该状态下的操做        
        System.out.println("我是项目经理,那臭小子一定有跑去面试了,哎,帮他一把,同意了,下个环节让老板审去");
        //直接进去老板审核状态
        context.setCurrentState(new BossState());
    }
}
复制代码
package com.design.state;

/**
 * 老板审核状态
 */
public class BossState extends State{

    public BossState(){
        super("Boss Audit", "老板审核环节");
    }

    @Override
    public void toNextState(Context context) {
        //项目经理审核状态,这里可以做该状态下的操做
        System.out.println("我是老板,我同意你请假了!!!流程结束!");
    }

}
复制代码

3、上下文类

package com.design.state;

public class Context {

    private State currentState;

    public Context(State state){
        currentState = state;
    }

    public void toNextState(){
        currentState.toNextState(this);
    };

    public State getCurrentState() {
        return currentState;
    }

    public void setCurrentState(State currentState) {
        this.currentState = currentState;
    }
}
复制代码

4、写好了,看下怎么调用

package com.design.state;

public class TestMain {

    public static void main(String[] args) {
        //创建申请休假单
        Context context = new Context(new AppState());
        System.out.println("状态:"+context.getCurrentState().getStateName());
        //提交申请
        context.toNextState();
        System.out.println("状态:"+context.getCurrentState().getStateName());
        //项目经理审核
        context.toNextState();
        System.out.println("状态:"+context.getCurrentState().getStateName());
        //老板审核
        context.toNextState();
    }
}复制代码

5、执行结果

设计模式之状态模式

五、优缺点

1、优点

(1)、将与特定状态相关的行为局部化,将不同状态的行为分割开来。

(2)、把状态转移逻辑分布到具体状态类中,减少相互间的依赖。

看不懂这两个优点??OK,我们来解释下,先来看看,不用状态模式,我们代码会怎么写?

package com.design.state;

public class StateChange {
    private int state = 0;

    private final static int APPLY=0; //申请状态
    private final static int PROJECTMANAGES=1;//项目经理审核状态
    private final static int BOSS=2;//老板审核状态
    private final static int FINISH=3;//流程结束状态

    public void toNextState(){
       switch (state){
           case 0:
               //申请状态,做点操作
               System.out.println("写申请书!!!");
               //进入项目经理审核状态
               state = PROJECTMANAGES;
               break;
           case 1:
               System.out.println("项目经理审核,同意你申请了");
               //进入老板审核状态
               state = BOSS;
               break;
           case 2:
               System.out.println("我是老板,同意你申请了");
               //进入结束状态
               state = FINISH;
               break;
           default:
               break;
       }
    }

}复制代码

你是不是写的跟我一样呢??有没有注意到,所有的操作,无论是哪个状态的操作都是在这个类中完成的,而使用状态模式,不同状态下的行为是定义在不同的状态类下的。这就是前面说的优点1。

我们状态切换是通过switch来判断状态,再决定下一个状态的,而在状态模式下,切换到下一个状态,是在具体的状态类下进行的,可以减少if之类的判断逻辑。这就是优点2。

2、缺点

(1)、状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。 

(2)、状态模式对"开闭原则"的支持并不太好,新增状态时,不仅得增加状态类,还得修改原来已经有的状态,让之前的状态切换到新增的状态。

六、总结说明

状态模式将原来通过判断实现的状态切换分散到各具体状态类中,比如上面切换到“老板审核状态”,是在“项目经理审核状态”中进行的,当状态比较多的情况,不容易理清各状态切换关系。同时它有将各状态的操作独立到状态类中,方便测试,还有分隔开各不同操作,便于阅读代码。实际运用中可根据自己的场景进行权衡。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C++Primer Plus

C++Primer Plus

Stephen Prata、孙建春、韦强 / 孙建春、韦强 / 人民邮电出版社 / 2005-5 / 72.00元

C++ Primer Plus(第五版)中文版,ISBN:9787115134165,作者:(美)Stephen Prata著;孙建春,韦强译一起来看看 《C++Primer Plus》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具