状态模式

49 阅读4分钟

状态模式

状态模式,它允许一个对象在其内部状态改变时改变它的行为。这个模式的核心思想是将对象的行为封装在不同的状态对象中,每个状态对象都代表了原对象的一个特定状态。当原对象的状态发生改变时,它会委托相应的行为给对应的状态对象来处理,从而实现了状态与行为之间的解耦。


结构

  • 环境(Context)角色:也称为上下文,它定义了客户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。

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

  • 具体状态(Concrete State)角色:实现抽象状态所对应的行为。

一切的行为委托给状态,每个状态独立为一个类,环境里维持一个当前状态,一切行为都由当前状态执行。如果当前状态执行一个行为会改变状态时,那就更新当前状态,再执行动作。

代码

package wnan.state;

/*****UTF-8*****
 * Description: 抽象状态
 * Author: wnan
 * Create Date: 2024/10/5 15:08
 * Proverbs: 吃得苦中苦,方为人上人
 */
public abstract class LiftState {
    /**
     * 目的:是为了与当前环境关联,当状态改变,去修改当前状态,而当前状态是右Context维护,所以有个Context实例对象
     */
    protected Context context;

    public void setContext(Context context) {
        this.context = context;
    }

    public abstract void open();
    public abstract void close();
    public abstract void run();
    public abstract void stop();
}
package wnan.state;

/*****UTF-8*****
 * Description: 开门状态
 * Author: wnan
 * Create Date: 2024/10/5 16:01
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class OpenState extends LiftState{
    @Override
    public void open() {
        System.out.println("open中");
    }

    @Override
    public void close() {
        /**
         * 修改的是状态,只能由对应的状态做出行为
         */
        super.context.setLiftState(Context.close);
        super.context.getLiftState().close();
    }

    @Override
    public void run() {
        System.out.println("open中,不能run");
    }

    @Override
    public void stop() {
        System.out.println("open中,已经stop");
    }
}
package wnan.state;

/*****UTF-8*****
 * Description: 运行状态
 * Author: wnan
 * Create Date: 2024/10/5 16:03
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class RunState extends LiftState {
    @Override
    public void open() {
        System.out.println("run中,不能open");
    }

    @Override
    public void close() {
        System.out.println("run中,已经close");
    }

    @Override
    public void run() {
        System.out.println("run中");
    }

    @Override
    public void stop() {
        this.context.setLiftState(Context.stop);
        this.context.getLiftState().stop();
    }
}
package wnan.state;

/*****UTF-8*****
 * Description: 关门状态
 * Author: wnan
 * Create Date: 2024/10/5 16:02
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class CloseState extends LiftState{
    @Override
    public void open() {
        this.context.setLiftState(Context.open);
        this.context.getLiftState().open();
    }

    @Override
    public void close() {
        System.out.println("close中");
    }

    @Override
    public void run() {
        this.context.setLiftState(Context.run);
        this.context.getLiftState().run();
    }

    @Override
    public void stop() {
        System.out.println("close中,已经stop");
    }
}
package wnan.state;

/*****UTF-8*****
 * Description: 停止状态
 * Author: wnan
 * Create Date: 2024/10/5 16:04
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class StopState extends LiftState {
    @Override
    public void open() {
        this.context.setLiftState(Context.open);
        this.context.getLiftState().open();
    }

    @Override
    public void close() {
        System.out.println("stop中,已经close");
    }

    @Override
    public void run() {
        this.context.setLiftState(Context.run);
        this.context.getLiftState().run();
    }

    @Override
    public void stop() {
        System.out.println("stop中");
    }
}
package wnan.state;

/*****UTF-8*****
 * Description: 环境接口
 * Author: wnan
 * Create Date: 2024/10/5 15:56
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class Context {
    public static final OpenState open=new OpenState();
    public static final CloseState close=new CloseState();
    public static final RunState run=new RunState();
    public static final StopState stop=new StopState();

    /**
     * 目的:这是环境,环境里只有一个当前状态暴露出去,环境的一切状态行为,只能由当前状态动作以及修改状态。Context要维护一个当前状态
     */
    private LiftState liftState;

    public LiftState getLiftState() {
        return liftState;
    }

    public void setLiftState(LiftState liftState) {
        this.liftState = liftState;
        this.liftState.setContext(this);
    }

    public void open(){
        this.liftState.open();
    }
    public void close(){
        this.liftState.close();
    }
    public void run(){
        this.liftState.run();
    }
    public void stop(){
        this.liftState.stop();
    }
}
package wnan.state;

/*****UTF-8*****
 * Description: 状态模式
 * Author: wnan
 * Create Date: 2024/10/5 14:34
 * Proverbs: 吃得苦中苦,方为人上人
 */
public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        context.setLiftState(Context.open);
        context.open();
        context.run();
        context.close();
        context.run();
        context.open();
    }
}

运行结果:

open中
open中,不能run
close中
run中
run中,不能open

源码 design_pattern

分析

优点:

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

允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。

缺点:

状态模式的使用必然会增加系统类和对象的个数。

状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。

状态模式对"开闭原则"的支持并不太好。

使用场景:

当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。

一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时