状态模式
目录当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。
状态模式的核心是封装,状态的变更引起了行为的变更,从外部看起来就好像这个对象 对应的类发生了改变一样。
优点
- 结构清晰。避免了过多的switch...case或者if...else语句的使用, 避免了程序的复杂性,提高系统的可维护性 。
- 遵循设计原则 。
- 封装性非常好 。
缺点
子类会太多, 也就是类膨胀。
适用场景
- 行为随状态改变而改变的场景。例如权限设计,人员的状态不同即使执行相同的行为结果也会不同, 在这种情况下需要考虑使用状态模式。
- 条件、 分支判断语句的替代者。
注意事项
状态模式适用于当某个对象在它的状态发生改变时, 它的行为也随着发生比较大的变化, 也就是说在行为受状态约束的情况下可以使用状态模式, 而且使用时对象的状态最好不要超过5个。 —来源《设计模式之禅 第二版》
通用类图
classDiagram Context o.. State State <|-- ConcreteState class State{ +handle() } class Context{ +request() }例子
电梯的开门、关门、运行、停止状态的变化
- 上下文
/**
* 上下文
*
* @author admin
*/
public class Context {
//定义出所有的电梯状态
public final static OpenningState OPENNING_STATE = new OpenningState();
public final static ClosingState CLOSEING_STATE = new ClosingState();
public final static RunningState RUNNING_STATE = new RunningState();
public final static StoppingState STOPPING_STATE = 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();
}
}
- 抽象状态角色
/**
* 抽象状态角色
*
* @author admin
*/
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();
}
- 开门状态
/**
* 开门状态
*
* @author admin
*/
public class OpenningState extends LiftState {
//开启当然可以关闭了, 我就想测试一下电梯门开关功能
@Override
public void close() {
//状态修改
super.context.setLiftState(Context.CLOSEING_STATE);
//动作委托为CloseState来执行
super.context.getLiftState().close();
}
//打开电梯门
@Override
public void open() {
System.out.println("电梯门开启...");
}
@Override
public void run() {
//do nothing;
}
//开门还不停止?
public void stop() {
//do nothing;
}
}
- 关门状态
/**
* 关闭状态
*
* @author admin
*/
public class ClosingState extends LiftState {
//电梯门关闭, 这是关闭状态要实现的动作
@Override
public void close() {
System.out.println("电梯门关闭...");
}
//电梯门关了再打开
@Override
public void open() {
super.context.setLiftState(Context.OPENNING_STATE); //置为敞门状态
super.context.getLiftState().open();
}
//电梯门关了就运行,这是再正常不过了
@Override
public void run() {
super.context.setLiftState(Context.RUNNING_STATE); //设置为运行状态
super.context.getLiftState().run();
}
//电梯门关着,我就不按楼层
@Override
public void stop() {
super.context.setLiftState(Context.STOPPING_STATE); //设置为停止状态
super.context.getLiftState().stop();
}
}
- 运行状态
/**
* 运行状态
*
* @author admin
*/
public class RunningState extends LiftState {
//电梯门关闭? 这是肯定的
@Override
public void close() {
//do nothing
}
//运行的时候开电梯门?你疯了!电梯不会给你开的
@Override
public void open() {
//do nothing
}
//这是在运行状态下要实现的方法
@Override
public void run() {
System.out.println("电梯上下运行...");
}
//这绝对是合理的,只运行不停止还有谁敢坐这个电梯? !估计只有上帝了
@Override
public void stop() {
//环境设置为停止状态
super.context.setLiftState(Context.STOPPING_STATE);
super.context.getLiftState().stop();
}
}
- 停止状态
/**
* 关闭状态
*
* @author admin
*/
public class StoppingState extends LiftState {
//停止状态关门? 电梯门本来就是关着的!
@Override
public void close() {
//do nothing;
}
//停止状态,开门,那是要的!
@Override
public void open() {
super.context.setLiftState(Context.OPENNING_STATE);
super.context.getLiftState().open();
}
//停止状态再运行起来,正常得很
@Override
public void run() {
super.context.setLiftState(Context.RUNNING_STATE);
super.context.getLiftState().run();
}
//停止状态是怎么发生的呢?当然是停止方法执行了
@Override
public void stop() {
System.out.println("电梯停止了...");
}
}
- 客户端
/**
* 客户端
*
* @author admin
*/
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();
}
}
- 运行结果
电梯门开启...
电梯门关闭...
电梯上下运行...
电梯停止了...
状态模式与策略模式的差异
状态模式通用类图
classDiagram Context o.. State : +state State <|-- ConcreteState class State{ +handle() } class Context{ +ContextInterface() +request() }策略模式通用类图
classDiagram Context o.. Strategy : +strategy Strategy <|-- ConcreteStrategy class Strategy{ +AlgorithmInterface() } class Context{ +ContextInterface() }区别:策略模式封装的是不同的算法, 算法之间没有交互, 以达到算法可以自由切换的目的; 而状态模式封装的是不同的状态, 以达到状态切换行为随之发生改变的目的。
标签:状态,Context,void,模式,context,Override,设计模式,public From: https://www.cnblogs.com/kouhao/p/17579621.html