设计模式之状态模式

栏目: 后端 · 发布时间: 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)、状态模式对"开闭原则"的支持并不太好,新增状态时,不仅得增加状态类,还得修改原来已经有的状态,让之前的状态切换到新增的状态。

六、总结说明

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


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

查看所有标签

猜你喜欢:

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

Web Development Recipes

Web Development Recipes

Brian P. Hogan、Chris Warren、Mike Weber、Chris Johnson、Aaron Godin / Pragmatic Bookshelf / 2012-1-22 / USD 35.00

You'll see a full spectrum of cutting-edge web development techniques, from UI and eye candy recipes to solutions for data analysis, testing, and web hosting. Make buttons and content stand out with s......一起来看看 《Web Development Recipes》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具