状态模式
状态模式,它允许一个对象在其内部状态改变时改变它的行为。这个模式的核心思想是将对象的行为封装在不同的状态对象中,每个状态对象都代表了原对象的一个特定状态。当原对象的状态发生改变时,它会委托相应的行为给对应的状态对象来处理,从而实现了状态与行为之间的解耦。
结构
-
环境(Context)角色:也称为上下文,它定义了客户程序需要的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
-
抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
-
具体状态(Concrete State)角色:实现抽象状态所对应的行为。
一切的行为委托给状态,每个状态独立为一个类,环境里维持一个当前状态,一切行为都由当前状态执行。如果当前状态执行一个行为会改变状态时,那就更新当前状态,再执行动作。
代码
package wnan.state;
/*****UTF-8*****
* Description: 抽象状态
* Author: wnan
* Create Date: 2024/10/5 15:08
* Proverbs: 吃得苦中苦,方为人上人
*/
public abstract class LiftState {
/**
* 目的:是为了与当前环境关联,当状态改变,去修改当前状态,而当前状态是右Context维护,所以有个Context实例对象
*/
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();
}
package wnan.state;
/*****UTF-8*****
* Description: 开门状态
* Author: wnan
* Create Date: 2024/10/5 16:01
* Proverbs: 吃得苦中苦,方为人上人
*/
public class OpenState extends LiftState{
@Override
public void open() {
System.out.println("open中");
}
@Override
public void close() {
/**
* 修改的是状态,只能由对应的状态做出行为
*/
super.context.setLiftState(Context.close);
super.context.getLiftState().close();
}
@Override
public void run() {
System.out.println("open中,不能run");
}
@Override
public void stop() {
System.out.println("open中,已经stop");
}
}
package wnan.state;
/*****UTF-8*****
* Description: 运行状态
* Author: wnan
* Create Date: 2024/10/5 16:03
* Proverbs: 吃得苦中苦,方为人上人
*/
public class RunState extends LiftState {
@Override
public void open() {
System.out.println("run中,不能open");
}
@Override
public void close() {
System.out.println("run中,已经close");
}
@Override
public void run() {
System.out.println("run中");
}
@Override
public void stop() {
this.context.setLiftState(Context.stop);
this.context.getLiftState().stop();
}
}
package wnan.state;
/*****UTF-8*****
* Description: 关门状态
* Author: wnan
* Create Date: 2024/10/5 16:02
* Proverbs: 吃得苦中苦,方为人上人
*/
public class CloseState extends LiftState{
@Override
public void open() {
this.context.setLiftState(Context.open);
this.context.getLiftState().open();
}
@Override
public void close() {
System.out.println("close中");
}
@Override
public void run() {
this.context.setLiftState(Context.run);
this.context.getLiftState().run();
}
@Override
public void stop() {
System.out.println("close中,已经stop");
}
}
package wnan.state;
/*****UTF-8*****
* Description: 停止状态
* Author: wnan
* Create Date: 2024/10/5 16:04
* Proverbs: 吃得苦中苦,方为人上人
*/
public class StopState extends LiftState {
@Override
public void open() {
this.context.setLiftState(Context.open);
this.context.getLiftState().open();
}
@Override
public void close() {
System.out.println("stop中,已经close");
}
@Override
public void run() {
this.context.setLiftState(Context.run);
this.context.getLiftState().run();
}
@Override
public void stop() {
System.out.println("stop中");
}
}
package wnan.state;
/*****UTF-8*****
* Description: 环境接口
* Author: wnan
* Create Date: 2024/10/5 15:56
* Proverbs: 吃得苦中苦,方为人上人
*/
public class Context {
public static final OpenState open=new OpenState();
public static final CloseState close=new CloseState();
public static final RunState run=new RunState();
public static final StopState stop=new StopState();
/**
* 目的:这是环境,环境里只有一个当前状态暴露出去,环境的一切状态行为,只能由当前状态动作以及修改状态。Context要维护一个当前状态
*/
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 wnan.state;
/*****UTF-8*****
* Description: 状态模式
* Author: wnan
* Create Date: 2024/10/5 14:34
* Proverbs: 吃得苦中苦,方为人上人
*/
public class Client {
public static void main(String[] args) {
Context context = new Context();
context.setLiftState(Context.open);
context.open();
context.run();
context.close();
context.run();
context.open();
}
}
运行结果:
open中
open中,不能run
close中
run中
run中,不能open
分析
优点:
将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
缺点:
状态模式的使用必然会增加系统类和对象的个数。
状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
状态模式对"开闭原则"的支持并不太好。
使用场景:
当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时