设计模式与应用:状态模式

版权声明: https://blog.csdn.net/maoyuanming0806/article/details/80317324

本文主要介绍状态模式的原理和应用场景,并与策略模式、责任链模式进行对比

简介

State模式也叫状态模式,是行为设计模式的一种。

State模式允许通过改变对象的内部状态而改变对象的行为,这个对象表现的就好像修改了他的类一样。

状态模式的应用场景

主要解决:当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转译到表现不同状态的一系列类当中,可以把复杂的判断逻辑简化。

结构图

这里写图片描述

角色和职责

  • Context 用户对象。拥有State类型的成员,以标识对象的当前状态
  • State 接口或基类。封装与Context的特定状态相关的行为
  • ConcreteState 接口实现类或子类,实现了一个与Context某个状态相关的行为

实现

这里写图片描述

状态作用对象

package com.mym.designmodel.State;

/**
 * 职责:Context 用户对象。拥有State类型的成员,以标识对象的当前状态
 */
public class Worker {

    private State state;

    private int hour;

    public Worker(){
        state = new AMState();
    }

    public int getHour() {
        return hour;
    }

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

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

    public State getState() {
        return state;
    }

    public void doWork(){
        state.doWorker(this);
        state = new AMState();//复原状态。当状态走到最后时复原到最初状态
    }
}

抽象状态

package com.mym.designmodel.State;

/**
 * 职责:State 接口或基类。封装与Context的特定状态相关的行为
 */
public abstract class State {
    public abstract void doWorker(Worker worker);
}

具体各个状态:上午状态

package com.mym.designmodel.State;

/**
 * 职责:ConcreteState 接口实现类或子类,实现了一个与Context某个状态相关的行为
 */
public class AMState extends State {
    @Override
    public void doWorker(Worker worker) {
        if(worker.getHour() == 9){
            System.out.println("做上午的事情!");
        }else{
            worker.setState(new PMState());
            worker.doWork();
        }
    }
}

具体各个状态:下午状态

package com.mym.designmodel.State;

/**
 * 职责:ConcreteState 接口实现类或子类,实现了一个与Context某个状态相关的行为
 */
public class PMState extends State {
    @Override
    public void doWorker(Worker worker) {
        if(worker.getHour() == 15){
            System.out.println("做下午的事情!");
        }else{
            worker.setState(new NightState());
            worker.doWork();
        }
    }
}

具体各个状态:晚上状态

package com.mym.designmodel.State;

/**
 * 职责:ConcreteState 接口实现类或子类,实现了一个与Context某个状态相关的行为
 */
public class NightState extends State {
    @Override
    public void doWorker(Worker worker) {
        if(worker.getHour() == 20){
            System.out.println("做晚上的事情!");
        }else{
            worker.setState(new NoState());
            worker.doWork();
        }
    }
}

具体各个状态:未定义状态

package com.mym.designmodel.State;

/**
 * 职责:ConcreteState 接口实现类或子类,实现了一个与Context某个状态相关的行为
 */
public class NoState extends State {
    @Override
    public void doWorker(Worker worker) {
        System.out.println(worker.getHour()+":未定义该做什么事情!");
    }
}

测试

package com.mym.designmodel.State;

/**
 * 测试
 */
public class MainClass {
    public static void main(String[] args) {
        Worker worker = new Worker();
        worker.setHour(9);
        worker.doWork();

        worker.setHour(15);
        worker.doWork();

        worker.setHour(20);
        worker.doWork();

        worker.setHour(23);
        worker.doWork();

        //这里测试复原,如果状态没有复原,这里将是未定义状态
        worker.setHour(9);
        worker.doWork();
    }
}

结果:

做上午的事情!
做下午的事情!
做晚上的事情!
23:未定义该做什么事情!
做上午的事情!

需要注意的是状态的复位。如果Worker最后一个状态执行完后,没有复位那么接下来该Worker都处于最后一个状态。执行结果就如下:

做上午的事情!
做下午的事情!
做晚上的事情!
23:未定义该做什么事情!
9:未定义该做什么事情!

状态模式思考于策略模式、责任链模式

状态模式和策略模式实际上都是根据不同条件执行不同事情。但是:

  • 状态模式更加关注的是类内部状态迁移,对外(客户端)不可见,客户端只需要按照既定的执行流程调用即可
  • 策略模式更加关注的是外部主动选择执行流程。

状态模式之于责任链模式,可能觉得这状态迁移很像责任链链式的执行。但是:

  • 状态模式每个状态都是同等层次,没有执行体的上下游
  • 责任链模式每个节点都是有执行先后顺序,关注的是整体共同完成一件事。
阅读更多

扫码向博主提问

maoyuanming0806

非学,无以致疑;非问,无以广识
去开通我的Chat快问
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页