Java设计模式学习记录-状态模式 Java设计模式学习记录-GoF设计模式概述

前言

状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题。状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态能够灵活多变。这样在客户端使用时无需关心对象的状态,能够实现自身的一致性处理。最近工做有些忙,更新博客慢了。仍是要严格要求本身的,抽时间也要坚持学习。 html

状态模式

概念介绍

状态模式容许一个对象在其状态改变时,改变它的行为,对象看起来彷佛修改了它的类。设计模式

想要在改变自身状态时改变对象行为,最直接的方法就是在代码中将全部可能发生的状况都考虑到了,而后使用if-else语句来进行相应的选择。可是这种方法对于复杂的状态判断会显得杂乱无章,容易产生错误;并且增长一个新的状态将会带来大量的修改。app

流程结构以下图:ide

此时“可以修改自身”的状态模式的引入也许是个不错的主意,将不一样条件下的行为封装在一个类里,再给这些类一个统一的父类来约束它们。post

就会变成以下图流程结构:学习

举例

仍是来举个具体的实例来讲明一下吧。同事小王要请假,根据公司规定,请假要先在OA上提请假申请单,而后审批经过后就能够正常休假了。这个请假申请单大体经历这么几个状态,未审核(待提交)、审核中、审核经过、审核未经过,这里只是粗略的分为这几个状态。下面咱们使用状态模式来模拟实现一下这个请假申请单的状态流转过程。测试

先建立一个休假申请单类url

/**
 * 休假申请
 */
public class LeaveApply {
    /**
     * 休假申请单初始状态是待提交状态
     */
    private ApplyState applyState = new UnAudited();

    /**
     * 设置状态
     * @param state
     */
    public void setState(ApplyState state){
        applyState = state;
    }

    /**
     * 状态变化后,更新对象自身的行为
     */
    public void update(){
        applyState.changeHandle();
    }

}

审批单状态接口,声明统一处理的方法。spa

/**
 * 审批单状态接口
 */
public interface ApplyState {

    /**
     * 状态变化处理操做
     */
    void changeHandle();

}

待提交状态设计

/**
 * 未审核状态(待提交审核)
 */
public class UnAudited implements ApplyState {
    /**
     * 状态变化处理操做
     */
    @Override
    public void changeHandle() {
        System.out.println("申请单处于未审核状态,当用户查看申请单详情时直接跳转到编辑页。");
    }
}

审核中状态

/**
 * 审核中状态
 */
public class Audit implements ApplyState {
    /**
     * 状态变化处理操做
     */
    @Override
    public void changeHandle() {
        System.out.println("申请单处于审核中状态,当用户查看申请单详情时跳转到详情页能够看到提交记录。");
    }
}

审核经过状态

/**
 *
 * 审核经过状态
 */
public class Pass implements ApplyState {
    /**
     * 状态变化处理操做
     */
    @Override
    public void changeHandle() {
        System.out.println("申请单已经审批经过,当前用户能够正常休假了。");
    }
}

审核未经过状态

/**
 * 审核未经过状态
 */
public class NotPass implements ApplyState {
    /**
     * 状态变化处理操做
     */
    @Override
    public void changeHandle() {
        System.out.println("申请单未经过审核,当前用户不能够休假");
    }
}

测试类

public class TestOA {

    public static void main(String[] args) {

        //建立一个请假申请单
        LeaveApply leaveApply = new LeaveApply();

        leaveApply.setState(new UnAudited());
        leaveApply.update();

        leaveApply.setState(new Audit());
        leaveApply.update();

        leaveApply.setState(new Pass());
        leaveApply.update();

        leaveApply.setState(new NotPass());
        leaveApply.update();


    }
}

运行结果:

申请单处于未审核状态,当用户查看申请单详情时直接跳转到编辑页。
申请单处于审核中状态,当用户查看申请单详情时跳转到详情页能够看到提交记录。
申请单已经审批经过,当前用户能够正常休假了。
申请单未经过审核,当前用户不能够休假

这个例子若是是不使用状态模式的思想,而是使用条件语句来实现就会出现不少的if-else来进行判断什么状态,应该执行什么样的方法。如今把各个状态的处理逻辑分离,结构清晰了而且耦合也不那么紧密了。

结构分析

在状态模式中引入了抽象状态类和具体状态类,它们是状态模式的核心。状态模式的结构组成以下图:

在状态模式中,主要涉及了以下几个角色。

环境角色(Context):定义客户端所感兴趣的接口,而且保留一个具体状态类的实例。这个具体状态类的实例给出此环境对象的现有状态。

抽象状态角色(State):定义一个接口,用以封装环境(Context)对象的一个特定的状态所对应的行为。

具体状态角色(Contract):每个具体状态类都实现了环境(Context)的一个状态所对应的行为。

总结

状态模式在功能上和策略模式很相似,可是在实现思想上状态模式是将各个状态分离解耦的,而且能够将对象的具体行为委托给当前的状态对象,而策略模式中,策略的选择是根据Context类中的行为来肯定的,也不存在各个状态的切换。在实际开发中,状态模式具备较高的使用频率,在工做流和游戏开发中状态模式都获得了普遍的应用,例如公文状态的转换、游戏中角色的升级等。

主要优势

一、封装了状态的转换规则,在状态模式中能够将状态转换的工做封装在环境类或具体的状态类中,能够对状态转换码进行集中管理,而不是分散在一个个的业务中。

二、将全部与某个状态有关的行为放到一个类中,只须要注入一个不一样的状态对象便可使环境对象拥有不一样的行为。

三、容许状态转换逻辑与状态对象合为一体,而不是提供一个巨大的条件语句块,状态模式可让咱们避免使用庞大的条件语句来将业务方法和状态转换代码交织在一块儿。

主要缺点

一、状态模式的使用必然会增长系统中类和对象的个数,致使系统运行开销增大。

二、状态模式的结构与实现都较为复杂,若是使用不当将致使程序结构和代码的混乱,增长系统设计的难度。

使用场景

一、对象的行为依赖于它的状态(如某些属性值),状态的改变将致使行为的变化。

二、在代码中包含大量与对象状态有关的条件语句,这些条件语句的出现,会致使代码的可维护性和灵活性变差,不能方便地增长和删除状态,而且致使客户类与类库之间的耦合加强。

 

 

 

想了解更多的设计模式请查看Java设计模式学习记录-GoF设计模式概述

 

这个是个人我的公众号,文章之后也会同步到公众号上去,欢迎关注。

相关文章
相关标签/搜索