设计模式(20)-状态模式

简介

为什么要使用状态模式

在软件设计的过程中,有些对象可能是有可以改变的状态的,而且对象的行为会随着状态的改变而改变。这种情况下,类的设计中就可能有大量的判断语句,而且如果新增了新的状态,类的设计就必须随之改变。在状态模式中,我们将对象在每一个状态下的行为和状态转移语句封装在一个个状态类中,允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

什么是状态模式

状态模式(State Pattern) :允许一个对象在其内部状态改变时改变它的行为,对象看起来似乎修改了它的类。

别名

状态对象(Objects for States)

类型

对象行为型模式

角色

角色

  • Context: 环境类
    • 具体类
    • 定义了客户程序需要的接口。
    • 维护一个具体状态角色ConcreteState的实例,这个实例定义当前状态。
  • State: 抽象状态类
    • 抽象类
    • 具体状态类的父类。
    • 定义一个接口以封装与环境类Context的一个特定状态相关的行为。
    • 声明了各种不同状态对应的方法。
  • ConcreteState: 具体状态类
    • 具体类
    • 继承了抽象状态类。
    • 每一个实现一个与Context的一个状态相关的行为。

UML类图

实现

  • 创建环境类Context.java
  • 创建抽象状态类State.java
  • 创建具体状态类ConcreteState.java
  • 创建测试类Client.java

环境类
Context.java

class Context {
    private State state; // 维持一个对抽象状态对象的引用
    // 设置状态对象

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

    // 转换状态。这里是不遵守“开闭原则的部分”。要新增新的状态,必须要修改这里的代码。
    public void changeValue(int value) {
        // 判断属性值,根据属性值进行状态转换
        if (value == 0) {
            this.setState(new ConcreteStateA());
        } else if (value == 1) {
            this.setState(new ConcreteStateB());
        }
    }

    public void request() {
        // 其他代码
        state.handle(this); // 调用状态对象的业务方法
        // 其他代码
    }
}

抽象状态类
State.java

abstract class State {
    // 声明抽象业务方法,不同的具体状态类可以不同的实现
    public abstract void handle(Context context);
}

具体状态类
ConcreteStateA.java

class ConcreteStateA extends State {    
    public void handle(Context context) {
        System.out.println("当前状态是 A.");
    }
}

ConcreteStateB.java

class ConcreteStateB extends State {
    public void handle(Context context) {
        System.out.println("当前状态是B.");
    }
}

测试类
Client.java

public class Client {
    public static void main(String[] args) {
        Context c = new Context();
        ConcreteStateA state = new ConcreteStateA();
        c.setState(state);
        c.request();
        c.changeValue(1);
        c.request();
        c.changeValue(0);
        c.request();

    }
}

测试
测试Client.java的main()

当前状态是 A.
当前状态是B.
当前状态是 A.

优缺点

优点

  • 封装了转换规则。
  • 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。

缺点

  • 不遵守“开闭原则”,增加新的状态类需要修改那些负责状态转换的源代码
public void changeValue(int value) {
    // 判断属性值,根据属性值进行状态转换
    if (value == 0) {
        this.setState(new ConcreteStateA());
    } else if (value == 1) {
        this.setState(new ConcreteStateB());
    }
}

适用环境

  • 一个对象的行为取决于它的状态,而且这个对象必须在运行时根据状态改变它的行为。
  • 在代码中包含大量与对象状态有关的条件语句。

使用场景

  • 政府OA办公系统
  • 审批流
  • TCP连接协议

扩展

相关模式

  • 享元模式Flyweight:解释了何时以及怎样共享状态对象。
  • 状态模式通常是Singleton

问题

在软件开发中,你在哪里用到了状态模式?

待补充。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值