当前位置: 代码迷 >> 综合 >> 设计模式学习之屡屡清楚状态模式
  详细解决方案

设计模式学习之屡屡清楚状态模式

热度:27   发布时间:2024-02-05 15:36:48.0

定义:

当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。状态模式的核心是封装,由于对象内部状态的改变,从而使这个类改变了其行为,看起来就像是换了一个类一样。

三个角色:

  • State抽象状态角色

接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换。

  • ConcreteState具体状态角色

每一个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理,通俗地说,就是本状态下要做的事情,以及本状态如何过渡到其他状态。

  • Context环境角色

定义客户端需要的接口,并且负责具体状态的切换。

代码示例:

package com.statechanges;/*** 环境角色*/
public class Context {//电梯状态public final static OpenningState openningState = new OpenningState();public final static CloseingState closeingState = new CloseingState();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.statechanges;/*** 抽象电梯状态类*/
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();
}package com.statechanges;public class OpenningState extends LiftState {//打开电梯@Overridepublic void open() {System.out.println("电梯门开启");}@Overridepublic void close() {//状态修改super.context.setLiftState(Context.closeingState);//动作委托为CloseState来执行super.context.getLiftState().close();}@Overridepublic void run() {}@Overridepublic void stop() {}
}package com.statechanges;public class CloseingState extends LiftState {//电梯门关了再打开@Overridepublic void open() {super.context.setLiftState(Context.openningState);//设置为敞门状态super.context.getLiftState().open();}@Overridepublic void close() {System.out.println("电梯门关闭");}//电梯门关了,电梯开始运行@Overridepublic void run() {super.context.setLiftState(Context.runningState);super.context.getLiftState().run();}@Overridepublic void stop() {super.context.setLiftState(Context.stoppingState);super.context.getLiftState().stop();}
}package com.statechanges;public class RunningState extends LiftState {//电梯运行期间,电梯门是关着的@Overridepublic void open() {}@Overridepublic void close() {}@Overridepublic void run() {System.out.println("电梯正在上下运行");}@Overridepublic void stop() {super.context.setLiftState(Context.stoppingState);super.context.getLiftState().stop();}
}package com.statechanges;public class StoppingState extends LiftState {@Overridepublic void open() {super.context.setLiftState(Context.openningState);//设置为敞门状态super.context.getLiftState().open();}@Overridepublic void close() {}@Overridepublic void run() {super.context.setLiftState(Context.runningState);super.context.getLiftState().run();}@Overridepublic void stop() {System.out.println("电梯停止了");}
}package com.statechanges;/*** 状态模式*/
public class Client {public static void main(String[] args) {Context context = new Context();context.setLiftState(new CloseingState());context.open();context.close();context.run();context.stop();}
}//打印结果
电梯门开启
电梯门关闭
电梯正在上下运行
电梯停止了

总结:

优点:

结构清晰:避免了过多的switch...case或者if...else语句的使用,避免了程序的复杂性,提高系统的可维护性。

遵循设计原则:很好地体现了开闭原则和单一职责原则,每个状态都是一个子类,增加状态就要增加子类,修改状态,只修改一个子类就可以。

封装性非常好:这也是状态模式的基本要求,状态变换放置到类的内部来实现,外部的调用不用知道类内部如何实现状态和行为的变换。

缺点:

随着状态的增多,子类会变得更多,所以需要权衡状态值得设定,如果无法限制可以预先在数据库存储,这样就更有利于状态模式的使用。

摘自《设计模式之禅》

  相关解决方案