前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

1、Status状态模式

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

1.1、解释

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

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

使用场景:

总之,以后遇到一些关于状态比较多(对象的行为取决于它的当前状态),修改起来需要判断当前状态并且,是否可以过度到另一个状态的时候,可以使用 。使用状态模式更加专注于自己的事情,而不关系别人,讲case里面的数据作为了类。相当于主动权放到了自己手里

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

 
    //电梯门关闭  
    public function close() {  
        //电梯在什么状态下才能关闭  
        switch($this->state){  
            case ILift::OPENING_STATE:  //如果是则可以关门,同时修改电梯状态  
                $this->setState(ILift::CLOSING_STATE);  
            break;  
            case ILift::CLOSING_STATE:  //如果电梯就是关门状态,则什么都不做  
                //do nothing;  
                return ;  
            break;  
            case ILift::RUNNING_STATE: //如果是正在运行,门本来就是关闭的,也说明都不做  
                //do nothing;  
                return ;  
            break;  
            case ILift::STOPPING_STATE:  //如果是停止状态,本也是关闭的,什么也不做  
                //do nothing;  
                return ;  
            break;  
        }  
                echo 'Lift colse <br>';  
    }  
  
    //电梯门开启  
    public function open() {  
        //电梯在什么状态才能开启  
        switch($this->state){  
            case ILift::OPENING_STATE: //如果已经在门敞状态,则什么都不做  
                //do nothing;  
                return ;  
            break;  
            case ILift::CLOSING_STATE: //如是电梯时关闭状态,则可以开启  
                $this->setState(ILift::OPENING_STATE);  
            break;  
            case ILift::RUNNING_STATE: //正在运行状态,则不能开门,什么都不做  
            //do nothing;  
                return ;  
            break;  
            case ILift::STOPPING_STATE: //停止状态,淡然要开门了  
                $this->setState(ILift::OPENING_STATE);  
            break;  
        }  
        echo 'Lift open <br>';  
    }  
    ///电梯开始跑起来  
    public function run() {  
        switch($this->state){  
            case ILift::OPENING_STATE: //如果已经在门敞状态,则不你能运行,什么都不做  
                //do nothing;  
                return ;  
            break;  
            case ILift::CLOSING_STATE: //如是电梯时关闭状态,则可以运行  
                $this->setState(ILift::RUNNING_STATE);  
            break;  
            case ILift::RUNNING_STATE: //正在运行状态,则什么都不做  
                //do nothing;  
                return ;  
            break;  
            case ILift::STOPPING_STATE: //停止状态,可以运行  
                $this->setState(ILift::RUNNING_STATE);  
        }  
        echo 'Lift run <br>';  
    }  
  
    //电梯停止  
    public function stop() {  
        switch($this->state){  
            case ILift::OPENING_STATE: //如果已经在门敞状态,那肯定要先停下来的,什么都不做  
                //do nothing;  
                return ;  
            break;  
            case ILift::CLOSING_STATE: //如是电梯时关闭状态,则当然可以停止了  
                $this->setState(ILift::CLOSING_STATE);  
            break;  
            case ILift::RUNNING_STATE: //正在运行状态,有运行当然那也就有停止了  
                $this->setState(ILift::CLOSING_STATE);  
            break;  
            case ILift::STOPPING_STATE: //停止状态,什么都不做  
                //do nothing;  
                return ;  
            break;  
        }  
        echo 'Lift stop <br>';  
    }  
      
}  

1.2、示例代码

1.2.1、状态抽象类LiftState

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.1.1、电梯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.2.1.2、电梯Closing

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


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.2.1.3、电梯Running

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



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.2.1.4、电梯Stopping

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


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.2.2、状态应用对象/环境

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 void setLiftState(LiftState liftState) {
        this.liftState = liftState;
        this.liftState.setContext(this);
    }

    public LiftState getLiftState() {
        return liftState;
    }



    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();

    }
}