如何在建设银行网站预约纪念币,免费软件有哪些,汕尾市企业网站seo点击软件,学校网站建设情况说明书文章目录 前言状态模式1、状态模式介绍1.1 存在问题1.2 解决问题1.3 状态模式结构图 2、具体案例说明状态模式2.1 不使用状态模式2.2 使用状态模式 3、状态模式总结 前言
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示… 文章目录 前言状态模式1、状态模式介绍1.1 存在问题1.2 解决问题1.3 状态模式结构图 2、具体案例说明状态模式2.1 不使用状态模式2.2 使用状态模式 3、状态模式总结 前言
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中可以把复杂的判断逻辑简化。当然如果这个状态判断很简单那就没必要用状态模式了。
状态模式
1、状态模式介绍
状态模式State是一种行为型设计模式当一个对象的内在状态改变时允许改变其行为这个对象看起来像是改变了其类。可以说当到饭点了你就会主动去找饭吃
1.1 存在问题
通常情况下一个对象的行为会随着其内部状态的改变而发生变化这些行为通常被包含在相应的if...else 语句中导致代码难以维护和扩展。
1.2 解决问题
适用状态模式判断状态是否改变。
状态模式的思想是将每种可能的状态都封装成一个类因此可以在不改变原有代码的前提下动态地改变对象的行为。状态模式提供了一种简单的实现方式即通过定义一个state接口再定义具体的state子类Context类中持有一个state的引用在不同状态下分别委托给不同的state处理相应的请求。这种实现方式将原来的大类拆分成多个小类使得系统更加灵活、易于扩展符合开闭原则。 状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中可以把复杂的判断逻辑简化。当然如果这个状态判断很简单那就没必要用状态模式了。 1.3 状态模式结构图 State类抽象状态类定义一个接口以封装与Context的一个特定状态相关的行为。
/*** 抽象状态类*/
public abstract class State {public abstract void handle(Context context);
}Context类维护一个ConcreteState子类的实例这个实例定义当前的状态。
public class Context {private State state;/*** 初始化当前状态* param state*/public Context(State state) {this.state state;}public State getState() {return state;}public void setState(State state) {this.state state;System.out.println(当前状态this.state.getClass().getName());}/*** 对请求做处理并设置下一个状态*/public void request(){this.state.handle(this);}
}ConcreteState类具体状态每一个子类实现一个与Context的一个状态相关的行为。
/*** 具体状态类A*/public class ConcreteStateA extends State{/*** 设置ConcreteStateA的下一个状态是ConcreteStateB* param context*/Overridepublic void handle(Context context) {context.setState(new ConcreteStateB());}
}/*** 具体状态类B*/
public class ConcreteStateB extends State {/*** 设置ConcreteStateB的下一个状态是ConcreteStateA* param context*/Overridepublic void handle(Context context) {context.setState(new ConcreteStateA());}
}客户端发起请求调用
public class ClientTest {public static void main(String[] args) {// 初始状态为ConcreteStateAContext context new Context(new ConcreteStateA());// 不断请求不断改变请求状态context.request();context.request();context.request();}
}输出结果 2、具体案例说明状态模式 案例不同的工作时间做不同的事情 2.1 不使用状态模式
/*** 工作类*/public class Work {// 时间private int hour;// 是否完成工作任务private boolean workFinished false;public int getHour() {return hour;}public void setHour(int hour) {this.hour hour;}public boolean getWorkFinished() {return workFinished;}public void setWorkFinished(boolean workFinished) {this.workFinished workFinished;}/*** 工作时间段*/public void workTime() {if (hour 12) {System.out.println(当前时间 hour 点上午工作精神百倍。);} else if (hour 13) {System.out.println(当前时间 hour 点,饿了午饭犯困午休。);} else if (hour 17) {System.out.println(当前时间 hour 点,下午状态还可以继续敲代码。);} else {if (workFinished) {System.out.println(当前时间 hour 点下班回家了愉快结束一天。);} else {if (hour 21) {System.out.println(当前时间 hour 点又开始加班疲累之极**加班。);} else {System.out.println(当前时间 hour 点睡觉时间到了躺床就睡着。);}}}}
}客户端
public class WorkClient {public static void main(String[] args) {Work work new Work();// 早上work.setHour(9);work.workTime();work.setHour(11);work.workTime();// 中午work.setHour(12);work.workTime();//下午work.setHour(13);work.workTime();work.setHour(14);work.workTime();work.setHour(17);//工作未完成work.setWorkFinished(false);// 加班work.workTime();work.setHour(19);work.workTime();work.setHour(22);work.workTime();}
}结果显示 有没有发现什么问题workTime()这个方法已经违背了开闭原则了每次都要修改这个方法才得以扩展新的功能 2.2 使用状态模式
具体的结构类图
State类
/*** 状态类*/
public abstract class State {public abstract void workTime(Work work);
}Work工作类
/*** 工作类*/
public class Work {/*** 时间点*/private int hour;/*** 是否完成工作任务-是否到达下班条件*/private boolean workFinished false;/*** 当前状态-设置下一个状态*/private State currentState;/*** 初始化状态-上午*/public Work() {currentState new ForenoonState();}/*** 工作时间段-显示当前状态并切换到下一个状态*/public void workTime() {this.currentState.workTime(this);}public State getCurrentState() {return currentState;}public void setCurrentState(State currentState) {this.currentState currentState;}public int getHour() {return hour;}public void setHour(int hour) {this.hour hour;}public boolean getWorkFinished() {return workFinished;}public void setWorkFinished(boolean workFinished) {this.workFinished workFinished;}
}早上具体状态
/*** 早上具体状态*/
public class ForenoonState extends State {Overridepublic void workTime(Work work) {if (work.getHour() 12) {System.out.println(当前时间 work.getHour() 点上午工作精神百倍。);} else {// 超过12点就转入中午状态work.setCurrentState(new NoonState());work.workTime();}}
}中午具体状态
/*** 中午状态*/
public class NoonState extends State {Overridepublic void workTime(Work work) {if (work.getHour() 13) {System.out.println(当前时间 work.getHour() 点,饿了午饭犯困午休。);} else {// 超过13点就转入下午工作状态work.setCurrentState(new AfternoonState());work.workTime();}}
}下午具体状态
/*** 下午具体状态*/
public class AfternoonState extends State {Overridepublic void workTime(Work work) {if (work.getHour() 17) {System.out.println(当前时间 work.getHour() 点,下午状态还可以继续敲代码。);} else {// 超时17点就进去傍晚工作时间点work.setCurrentState(new EveingState());work.workTime();}}
}任务完成按时下班状态类
/*** 按时下班*/
public class RestState extends State {Overridepublic void workTime(Work work) {System.out.println(当前时间 work.getHour() 点下班回家咯);}
}工作任务未完成加班“累”
/*** 具体加班类*/
public class EveingState extends State {Overridepublic void workTime(Work work) {if (work.getWorkFinished()) {// 工作完成下班work.setCurrentState(new RestState());work.workTime();} else {// 工作没有完成则继续加班if (work.getHour() 21) {System.out.println(当前时间 work.getHour() 点又开始加班疲累之极**加班。);} else {// 到点睡觉work.setCurrentState(new SleepingState());work.workTime();}}}
}睡觉类
/*** 睡觉状态*/
public class SleepingState extends State {Overridepublic void workTime(Work work) {System.out.println(当前时间 work.getHour() 点睡觉时间到了躺床就睡着。);}
}客户端同上 最终的结果也同上 虽然结果相同但是我们的程序变得更加灵活比如公司要求在20点之前必须离开公司 此时我们就要新增一个“强制下班类”并改动一下 “晚间工作状态”类的判断就可以 了。而这是不影响其他状态的代码的。 实现加班类修改如下
/*** 具体加班类*/
public class EveingState extends State {Overridepublic void workTime(Work work) {if (work.getWorkFinished()) {// 工作完成下班work.setCurrentState(new RestState());work.workTime();} else {// 工作没有完成则继续加班work.setCurrentState(new ForcedLiveWork());work.workTime();}}
}强制下班类
/*** 强制下班*/
public class ForcedLiveWork extends State {Overridepublic void workTime(Work work) {if (work.getHour() 20) {System.out.println(当前时间 work.getHour() 点公司规定此刻必须要离开公司了。);} else {// 到点睡觉work.setCurrentState(new SleepingState());work.workTime();}}
}实现起来并不困难只需增加一个类再对去修改判断条件这样就不会影响到其他状态的代码
3、状态模式总结
状态模式的优点包括
将状态转换和行为隔离开来使得状态变化时只需要改变状态类对象即可无需修改Context类从而保证了系统的灵活性、可扩展性和可维护性。在状态模式中每个状态都被封装在一个类中增加新的状态类很方便符合开闭原则。通过引入抽象状态类和抽象环境类可以很好地解决代码的耦合问题。状态模式通过把各种状态转移逻辑分布到State的子类之间来减少相互间的依赖状态模式使得状态转换显式化了独立于具体的状态类之外更符合面向对象的设计思想。对于状态机的实现状态模式提供了一种设计思路和方法。将特定的状态相关的行为都放入一个对象中由于所有与 状态相关的代码都存在于某个ConcreteState中所以通过定义新的子类可 以很容易地增加新的状态和转换。消除大量的条件判断语句
状态模式的缺点包括
由于引入了多个子类因此在一定程度上增加了系统的复杂度使得系统抽象层次增加设计难度加大。如果状态改变很频繁则会导致系统中类的数量增加从而增加系统的维护难度。如果状态比较多且状态之间的转换比较复杂容易造成代码的混乱和不易维护。
状态模式适用场景
当一个对象的行为取决于它的状态并且它必须在运行时刻根据状态 改变它的行为时可以考虑使用状态模式。当对象的行为随着对象内部状态的变化而发生变化时可以考虑使用状态模式。例如电视机有开机、关机、切换频道等状态根据不同的状态做出相应的响应使用状态模式可以方便地实现。当系统中存在多种状态且状态之间存在转换关系时可以考虑使用状态模式。例如一个产品订单在待支付、已支付、已取消等多个状态之间转换可以使用状态模式来实现。当需要对状态进行动态修改时可以考虑使用状态模式。例如在游戏中玩家角色根据当前的状态有不同的技能和装备而这些状态是可以通过游戏中获得的物品进行修改的这时候就可以使用状态模式。当状态转换规则比较复杂或需要进行扩展时可以考虑使用状态模式。状态模式将状态转换规则封装在具体状态类中可以方便地对状态转换规则进行修改和扩展。当希望避免使用大量的if else语句提高代码可读性和可维护性时可以考虑使用状态模式。状态模式使得代码易于扩展和修改并且降低了代码的耦合度更符合面向对象的设计原则。