设计模式之管理状态_Status状态模式_用类保存状态

前言

博主github

博主个人博客http://blog.healerjean.com

1、解释

1、对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。

2、代码中包含大量与对象状态有关的条件语句:一个操作中含有庞大的多条件(if else 或switch case)语句,且这些条件依赖于该对象的状态。这个状态通常用一个或多个枚举常量表示。

 //运行动作
    @Override
    public void run() {
        switch (state) {
            case OPEN_STATE:
                System.out.println("处于开门状态:什么也不做");
                break;
            case CLOSE_STATE:
                System.out.println("处于关门状态:运行...");
                setState(RUN_STATE);
                break;
            case RUN_STATE:
                System.out.println("处于运行状态:什么也不做");
                break;
            case STOP_STATE:
                System.out.println("处于停止状态:运行...");
                setState(RUN_STATE);
        }
    }

通常 , 有多个操作包含这一相同的条件结构。 State模式将每一个条件分支放入一个独立的类中。这使得你可以根据对象自身的情况将对象的状态作为一个对象,这一对象可以不依赖于其他对象而独立变化。

1.1、状态抽象类

public abstract class LiftState {

    /**
     * 定义一个环境角色,也就是封装状态的变换引起的功能变化
     */
    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();


}

1.2、电梯Opening子类

public class OpenningState extends LiftState {

    
    @Override
    public void open() {
        System.out.println("电梯门开启...");
    }

    

    @Override
    public void close() {
        System.out.println("电梯准备从Openning状态到Closeing状态");
        super.context.setLiftState(Context.closeingState);
        super.context.getLiftState().close();
    }



    @Override
    public void run() {
        throw new RuntimeException("电梯在门开启下就是不可以运行,容易发生危险");
    }


    @Override
    public void stop() {
        throw new RuntimeException("电梯在门开启下就是停止状态,无须操作");

    }



}

1.3、电梯Closing

package com.hlj.moudle.design.D08管理状态.D19Status状态模式;

/**
 * @author HealerJean
 * @ClassName ClosingState
 * @date 2019-08-20  21:29.
 * @Description 电梯门关闭以后,电梯可以做哪些事情
 */
public class ClosingState extends LiftState {



    @Override
    public void open() {
        System.out.println("电梯准备从Closing状态到Opening状态");
        super.context.setLiftState(Context.openningState);
        super.context.getLiftState().open();
    }

    /**
     *  电梯门关闭,这是关闭状态要实现的动作
     */
    @Override
    public void close() {
        System.out.println("电梯门关闭...");
    }


    @Override
    public void run() {
        System.out.println("电梯准备从Closing状态到Runing状态");
        super.context.setLiftState(Context.runningState);
        super.context.getLiftState().run();
    }

    @Override
    public void stop() {
        System.out.println("电梯准备从Closing状态到Stoping状态");
        super.context.setLiftState(Context.stoppingState);
        super.context.getLiftState().stop();
    }
}

1.4、电梯RunningState子类

package com.hlj.moudle.design.D08管理状态.D19Status状态模式;

/**
 * @author HealerJean
 * @ClassName RunningState
 * @date 2019-08-20  21:30.
 * @Description电梯在运行状态下能做哪些动作
 */

public class RunningState extends LiftState {

    @Override
    public void open() {
        throw new RuntimeException("电梯在运行状态下门不可以打开");
    }

    
    @Override
    public void close() {
        throw new RuntimeException("电梯在运行状态下门肯定是关闭的");
    }

    @Override
    public void run() {
        System.out.println("电梯正在开始跑…………………………");
    }

    @Override
    public void stop() {
        System.out.println("电梯准备从Running状态到Stoping状态");
        super.context.setLiftState(Context.stoppingState);
        super.context.getLiftState().stop();
    }
}

1.5、电梯StoppingState子类

package com.hlj.moudle.design.D08管理状态.D19Status状态模式;

/**
 * @author HealerJean
 * @ClassName StoppingState
 * @date 2019-08-20  21:31.
 * @Description 在停止状态下能做什么事情
 */
public class StoppingState extends LiftState {

    @Override
    public void open() {
        System.out.println("电梯准备从Stopping状态到Opening状态");
        super.context.setLiftState(Context.openningState);
        super.context.getLiftState().open();
    }

    @Override
    public void close() {
        throw new RuntimeException("电梯停止状态下们就是关闭的");
    }

 
    @Override
    public void run() {
        System.out.println("电梯准备从Stopping状态到Running状态");
        super.context.setLiftState(Context.runningState);
        super.context.getLiftState().run();
    }


    @Override
    public void stop() {
        System.out.println("电梯停止了...");
    }
}

1.6、状态应用对象/环境

public class Context {

    /**
     * 定义出所有的电梯状态
     */
    public final static OpenningState openningState = new OpenningState();
    public final static ClosingState closeingState = new ClosingState();
    public final static RunningState runningState = new RunningState();
    public final static StoppingState stoppingState = new StoppingState();


    /**
     * 定一个当前电梯状态
     */
    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();
    }
}

1.7、测试

public class Z19Main {

    public static void main(String[] args) {
        Context context = new Context();
        context.setLiftState(new ClosingState());

        context.open();
        System.out.println("--------");
        context.close();
        System.out.println("--------");
        context.run();
        System.out.println("--------");
        context.stop();

    }
}














3、总结

状态模式,对我个人来说是没怎么用过的,因为在场景中我所使用的状态,都是直接从一个状态到另一个状态,直接修改的。其实仔细想想,也可以使用状态模式,比如现在小米这个里面有个产品的状态(关闭,开启,合同待配置,废弃),我们当我们关闭的时候,如果开启,需要判断合同需要配置,然后才能开启,如果合同配置则让他到合同待配置状态,

总之,以后遇到一些关于状态比较多(对象的行为取决于它的状态),修改起来需要判断当前状态并且,是否可以过度到另一个状态的时候,可以使用 。



感兴趣的,欢迎添加博主微信

哈,博主很乐意和各路好友交流,如果满意,请打赏博主任意金额,感兴趣的在微信转账的时候,备注您的微信或者其他联系方式。添加博主微信哦。

请下方留言吧。可与博主自由讨论哦

微信 微信公众号 支付宝
微信 微信公众号 支付宝
posted @ 2019-08-26 15:29  HealerJean  阅读(271)  评论(0编辑  收藏  举报