设计模式之管理状态_Status状态模式_用类保存状态
前言
Github:https://github.com/HealerJean
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();
}
}