阿里爸爸规范中提到了:"尽量不要使用else,if else语句,可使用卫语句或者状态设计模式来替换",那何谓状态设计模式呢?

问题:例如:电梯状态:开,关,运行,暂停,停电,故障等等...        电梯的行为:开门,升降,关门等...

状态决定了行为,行为又产生了某种状态,so很有意思吧,我们该如何合理的解决(遵循java设计的开闭原则)该问题呢?

解决方案:

1. 首先写个类A,里面定义所有的状态(常量 public static final),没毛病吧

2. 状态如何决定行为呢?每个状态都对应一个特定的类B,里面定义了各自的行为

3. 行为又如何产生特定的状态呢? 

*   我们先得解决一个 隐藏的问题:这个状态是哪个对象的状态呢?现在我们就写了两种类AB,哈哈不妨我们把类A设置成该对象,类B中都持有类A的对象不就好了(好吗?)。

*   如何指定A对象的状态呢,A中现在只包含几个状态常量,肯定是不行的,得有一个变量哈,顺便私有了,提供set,get方法,可是这个变量的类型写啥啊?

*   我们不妨把每个状态类B提取出来一个接口C,统一管理起来,变量的类型就知道怎么写了吧。类A的对象在每个状态类中都写一遍,不妨在接口中统一管理,岂不更好。

*   那么这个变量代表啥含义呢?当前状态

4.指定了当前状态,那么如何执行当前的行为呢?当前状态直接调用你想要的行为不就好了,一切顺利成章的完成啦。

5.还差最后一个中间桥梁,接口C中类A对象还没指定呢(用于改变类A中的状态),啥时候指定好呢?肯定使用之前啦!!!类A初始化或者指定当前状态的时候

6.那么如何调用的呢?指定A对象的当前状态,调用A的行为方法(A方法调用的是状态类B中的方法)


初始化状态-->决定特定的行为-->改变了当前状态--->决定下一步的行为  无限循环,代码也就活起来了


经典电梯代码附上:


接口C代码:

package com.cbf4life.advance;

/**

* @author cbf4Life cbf4life@126.com

* I'm glad to share my knowledge with you all.

* 定义一个电梯的接口

*/

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

}


类B代码(其中一个):

package com.cbf4life.advance;

/**

* @author cbf4Life cbf4life@126.com

* I'm glad to share my knowledge with you all.

* 在电梯门开启的状态下能做什么事情

*/

public class OpenningState extends LiftState {

//开启当然可以关闭了,我就想测试一下电梯门开关功能

@Override

public void close() {

//状态修改

super.context.setLiftState(Context.closeingState);

//动作委托为CloseState来执行

super.context.getLiftState().close();

}

//打开电梯门

@Override

public void open() {

System.out.println("电梯门开启...");

}

//门开着电梯就想跑,这电梯,吓死你!

@Override

public void run() {

//do nothing;

}

//开门还不停止?

public void stop() {

//do nothing;

}

}


类A代码如下:

package com.cbf4life.advance;

/**

* @author cbf4Life cbf4life@126.com

* I'm glad to share my knowledge with you all.

*/

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

}

}


调用类:

package com.cbf4life.advance;

/**

* @author cbf4Life cbf4life@126.com

* I'm glad to share my knowledge with you all.

* 模拟电梯的动作

*/

public class Client {

public static void main(String[] args) {

Context context = new Context();

context.setLiftState(new ClosingState());

context.open();

context.close();

context.run();

context.stop();

}

}