欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

设计模式之状态模式

程序员文章站 2024-03-24 19:24:58
...

前言:

状态模式(State Pattern)当一个对象的内在状态改变时,允许改变其行为。这个对象看起来像是改变了其类。

一.状态模式简介

状态模式(State Pattern)解决的是当控制一个对象状态的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列类当中,把复杂的判断逻辑简化了。

二.状态模式的实例讲解

案例:对一个人一天各个时刻的工作状态进行判断,根据状态改变工作行为。

1.产品设计UML类图

设计模式之状态模式
(图片加载慢,多刷新几下,耐心等待……)

注:工作状态类Work和状态抽象类State是聚合关系,State包含WORK,但不是WORK的一部分。

聚合关系:表示一种弱的"拥有"关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分。

2.状态抽象类

设计分析:定义一个接口,封装与工作状态类(Work类)的一个特定状态相关的行为(doSomeWork())。

package com.pattern.state.state;

import com.pattern.state.context.Work;

/**
 * 状态抽象类
 */
public abstract class State {
    public abstract void doSomeWork(Work work);

}

3.具体状态类

设计分析: 每个子类都实现一个与工作状态(Work)的一个状态相关的行为,这样做的目的是把各种状态的转移逻辑分布到State子类之间,来减少相互间的依赖。

在本例中,上午工作状态、下午工作状态、晚上工作状态、睡觉休息状态都继承自State抽象类,并实现与工作状态相关的行为(doSomeWork()方法)。

①上午工作状态类
package com.pattern.state.state;

import com.pattern.state.context.Work;

/**
 * 上午状态
 */
public class AMState extends State {

    @Override
    public void doSomeWork(Work work) {
        if (work.getHour()<12) {
            System.out.println("上午"+work.getHour()+"点钟,努力工作中……");
        }else {
            work.setState(new PMState());
            work.doSomeWork();
        }

    }

}
②下午工作状态类
package com.pattern.state.state;

import com.pattern.state.context.Work;

/**
 * 下午状态
 */
public class PMState extends State {

    @Override
    public void doSomeWork(Work work) {
        if (work.getHour()<18) {
            System.out.println("下午"+work.getHour()+"点钟,团队开会……");
        }else {
            work.setState(new NightState());
            work.doSomeWork();
        }

    }

}
③晚上工作状态类
package com.pattern.state.state;

import com.pattern.state.context.Work;

/**
 * 晚上状态
 */
public class NightState extends State {

    @Override
    public void doSomeWork(Work work) {

        if (work.isFinish()) {
            work.setState(new EndWorkState());
            work.doSomeWork();
        }else if (work.getHour()<23) {
            System.out.println(work.getHour()+"点钟,加班中……");
        }else if (work.getHour()>23){
            work.setState(new SleepState());
            work.doSomeWork();
        }


    }

}
④停止工作状态类
package com.pattern.state.state;

import com.pattern.state.context.Work;

/**
 * 结束工作状态
 */
public class EndWorkState extends State {

    @Override
    public void doSomeWork(Work work) {
        if (work.getHour()>23) {
            work.setState(new SleepState());
            work.doSomeWork();
        }else {
            System.out.println(work.getHour()+"点钟,工作完成了,终于下班了");
        }

    }

}
⑤休息睡觉状态类
package com.pattern.state.state;

import com.pattern.state.context.Work;


/**
 * 睡觉休息状态
 */
public class SleepState extends State {

    @Override
    public void doSomeWork(Work work) {
        System.out.println("晚上"+work.getHour()+"点钟,睡觉吧");
    }

}

4.工作状态类

设计分析: 维护一个State对象的具体实例,用于封装所有工作状态相关的代码。

package com.pattern.state.context;

import com.pattern.state.state.AMState;
import com.pattern.state.state.State;

/**
 * 工作状态
 */
public class Work {
    private State current;
    private double hour;// 判断状态变化的标准
    private boolean finish = false;// 工作完成的标志位

    public Work() {
        // 初始化为上午状态,从上午开始工作,定义当前状态
        this.current = new AMState();
    }

    public double getHour() {
        return hour;
    }

    public void setHour(double hour) {
        this.hour = hour;
    }

    public boolean isFinish() {
        return finish;
    }

    public void setFinish(boolean finish) {
        this.finish = finish;
    }

    public void doSomeWork() {
        current.doSomeWork(this);
    }

    public void setState(State s) {
        current = s;
    }
}

5.客户端中使用

package com.pattern.state.client;

import com.pattern.state.context.Work;

public class Client {
    public static void main(String[] args) {
        //创建状态对象
        Work work =new Work();
        //设置状态变化的标志
        work.setHour(9);
        //执行状态相关的行为
        work.doSomeWork();

        work.setHour(14);
        work.doSomeWork();

        work.setHour(18);
        work.doSomeWork();

        work.setHour(21);
        //完成工作了,设为true,默认为false
        work.setFinish(true);
        work.doSomeWork();

        work.setHour(24);
        work.doSomeWork();
    }
}

6.运行结果展示

在工作没有做完(work.setFinish(false))的情况下:

上午9.0点钟,努力工作中……
下午14.0点钟,团队开会……
18.0点钟,加班中……
21.0点钟,加班中……
晚上24.0点钟,睡觉吧

在工作做完(work.setFinish(true))的情况下:

上午9.0点钟,努力工作中……
下午14.0点钟,团队开会……
18.0点钟,加班中……
21.0点钟,工作完成了,终于下班了
晚上24.0点钟,睡觉吧

7.源码下载

本文示例代码下载地址:点击下载

三.总结:

当一个对象的行为取决于它的状态,并且需要在运行中根据状态改变它的行为的时候,就可以考虑使用状态模式了,状态模式是条件分支语句的代替者。

1.状态模式的优点

  • 封装了转换的规则
  • 将可能的状态分解到状态子类中,解除了各种状态之间的耦合,便于修改和扩展。
  • 状态逻辑和状态对象整合在一起,替代了庞大的条件语句块

2.状态模式的缺点

  • 增加类和对象的个数。
  • 开放-封闭原则支持不太好,当新增状态类的时候,需要修改负责状态转换的源码;修改状态类行为的时候,也要修改对应类的源码。