赞
踩
public class Main { public static int hour = 0;// 钟点 public static boolean workFinished = false; // 任务完成标记 /** * 定义一个“写程序”的函数,用来根据时间的不同体现不同的工作状态 */ public static void writeProgram() { if (hour < 12) { System.out.println(String.format("当前时间:%s点 上午工作,精神百倍", hour)); } else if (hour < 13) { System.out.println(String.format("当前时间:%s点 饿了,午饭;犯困,午休", hour)); } else if (hour < 17) { System.out.println(String.format("当前时间:%s点 下午状态还不错,继续努力", hour)); } else { if (workFinished) { System.out.println(String.format("当前时间:%s点 下班回家了", hour)); } else { if (hour < 21) { System.out.println(String.format("当前时间:%s点 加班哦,疲累之极", hour)); } else { System.out.println(String.format("当前时间:%s点 不行了,睡着了", hour)); } } } } public static void main(String[] args) { hour = 9; writeProgram(); hour = 10; writeProgram(); hour = 12; writeProgram(); hour = 13; writeProgram(); hour = 14; writeProgram(); hour = 17; writeProgram(); // workFinished = true; workFinished = false; // 任务完成,则可以下班,否则就要加班了 writeProgram(); hour = 19; writeProgram(); hour = 22; writeProgram(); } }
public class Work { private int hour; private boolean workFinished ; // 任务完成标记 public int getHour() { return hour; } public void setHour(int hour) { this.hour = hour; } public boolean isWorkFinished() { return workFinished; } public void setWorkFinished(boolean workFinished) { this.workFinished = workFinished; } /** * 定义一个“写程序”的函数,用来根据时间的不同体现不同的工作状态 */ public void writeProgram() { if (hour < 12) { System.out.println(String.format("当前时间:%s点 上午工作,精神百倍", hour)); } else if (hour < 13) { System.out.println(String.format("当前时间:%s点 饿了,午饭;犯困,午休", hour)); } else if (hour < 17) { System.out.println(String.format("当前时间:%s点 下午状态还不错,继续努力", hour)); } else { if (workFinished) { System.out.println(String.format("当前时间:%s点 下班回家了", hour)); } else { if (hour < 21) { System.out.println(String.format("当前时间:%s点 加班哦,疲累之极", hour)); } else { System.out.println(String.format("当前时间:%s点 不行了,睡着了", hour)); } } } } }
public class Client { public static void main(String[] args) { // 紧急项目 Work energencyProjects = new Work(); energencyProjects.setHour(9); energencyProjects.writeProgram(); energencyProjects.setHour(10); energencyProjects.writeProgram(); energencyProjects.setHour(12); energencyProjects.writeProgram(); energencyProjects.setHour(13); energencyProjects.writeProgram(); energencyProjects.setHour(14); energencyProjects.writeProgram(); energencyProjects.setHour(17); energencyProjects.writeProgram(); energencyProjects.setWorkFinished(false); energencyProjects.writeProgram(); energencyProjects.setHour(19); energencyProjects.writeProgram(); energencyProjects.setHour(22); energencyProjects.writeProgram(); } }
问题:work.writeProgram()方法过长了,这里面有太多的判断,意味着它的责任过大了。无论是任何状态,都需要通过它来改变,这是很糟糕的。面向对象设计其实就是希望做到代码的责任分解。这个类违背了“单一职责原则”和“开闭原则”。
状态模式,当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况。把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。当然,如果这个状态判断很简单,就没有必要使用“状态模式”了。
State类,抽象状态类,定义一个接口以封装与Context的一个特定状态相关的行为。
public abstract class State {
public abstract void handle(Context context);
}
ConcreteState类,具体状态,每一个子类实现一个与Context的一个状态相关的行为。
public class ConcreteStateA extends State {
@Override
public void handle(Context context) {
// 设置ConcreteStateA的下一状态是ConcreteStateB
context.setState(new ConcreteStateB());
}
}
public class ConcreteStateB extends State {
@Override
public void handle(Context context) {
// 设置ConcreteStateB的下一状态是ConcreteStateA
context.setState(new ConcreteStateA());
}
}
Context类,维护一个ConcreteState子类的实例,这个实例定义当前的状态。
public class Context { /** * 可读写的状态属性,用于读取当前状态和设置新状态 */ private State state; /** * 定义Context的初始状态 */ public Context(State state) { this.state = state; } public State getState() { return state; } public void setState(State state) { System.out.println("当前状态:"+state.getClass().getName()); this.state = state; } // 对请求做处理,并设置下一状态 public void request() { //...满足条件就设置下一状态 state.handle(this); } }
public class Client {
public static void main(String[] args) {
// 设置Context的初始状态为ConcreteStateA
Context context = new Context(new ConcreteStateA());
context.request();
context.request();
context.request();
context.request();
}
}
状态模式的好处是将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
将特定的状态相关的行为都放入一个对象中,由于所有与状态相关的代码都存在于某个ConcreteState中,所以通过定义新的子类可以很容易地增加新的状态和转换。
这样的目的是为了消除庞大的条件分支语句,大的分支判断会使它们难以修改和扩展。状态模式通过把各种状态转移逻辑分布到State的子类之间,来减少相互间的依赖。
什么时候应该考虑使用状态模式呢?
当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时,就可以考虑使用状态模式了。另外如果业务需求某项业务有多个状态,通常都是一些枚举常量,状态的变化都是依靠大量的多分支判断语句来实现,此时应该考虑将每一种业务状态定义为一个State的子类。这样这些对象就可以不依赖于其他对象而独立变化了。
// 抽象状态
public abstract class State {
public abstract void writeProgram(Work work);
}
// 上午工作状态
public class ForenoonState extends State {
@Override
public void writeProgram(Work work) {
if (work.getHour() < 12) {
System.out.println(String.format("当前时间:%s点 上午工作,精神百倍", work.getHour()));
} else {
// 超过12点,转入中午工作状态
work.setState(new NoonState());
work.writeProgram();
}
}
}
// 中午工作状态
public class NoonState extends State{
@Override
public void writeProgram(Work work) {
if (work.getHour() < 13) {
System.out.println(String.format("当前时间:%s点 饿了,午饭;犯困,午休", work.getHour()));
} else {
// 超过13点,则转入下午工作状态
work.setState(new AfternoonState());
work.writeProgram();
}
}
}
// 下午工作状态
public class AfternoonState extends State {
@Override
public void writeProgram(Work work) {
if (work.getHour() < 17) {
System.out.println(String.format("当前时间:%s点 下午状态还不错,继续努力", work.getHour()));
} else {
// 超过17点,则转入傍晚工作状态
work.setState(new EveningState());
work.writeProgram();
}
}
}
// 晚间工作状态 public class EveningState extends State { @Override public void writeProgram(Work work) { if (work.getWorkFinished()) { // 如果完成任务,则转入下班状态 work.setState(new RestState()); work.writeProgram(); } else { if (work.getHour() < 21) { System.out.println(String.format("当前时间:%s点 加班哦,疲累之极", work.getHour())); } else { // 超过21点,则转入睡眠工作状态 work.setState(new SleepingState()); System.out.println(String.format("当前时间:%s点 不行了,睡着了", work.getHour())); } } } }
// 睡眠状态
public class SleepingState extends State {
@Override
public void writeProgram(Work work) {
System.out.println(String.format("当前时间:%s点 不行了,睡着了", work.getHour()));
}
}
// 下班休息状态
public class RestState extends State {
@Override
public void writeProgram(Work work) {
System.out.println(String.format("当前时间:%s点 下班回家了", work.getHour()));
}
}
public class Work { private State state; /** * “钟点属性”,状态转换的依据 */ private int hour; /** * “任务完成属性”,是否能下班的依据 */ private boolean workFinished; public Work() { // 工作初始化为上午工作状态,即上午9点开始上班 state = new ForenoonState(); } public void writeProgram() { state.writeProgram(this); } 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 setState(State state) { this.state = state; } }
在上下文(work)中设置一个状态(成员变量state),在业务处理时,调用状态中的方法(state.writeProgram),如果状态不满足条件(work.hour),就调用满足条件的状态的那个方法(调另一个状态的writeProgram)。将以前if…else中的逻辑,分散到多个状态中。
public class Client { public static void main(String[] args) { Work energencyProjects = new Work(); energencyProjects.setHour(9); energencyProjects.writeProgram(); energencyProjects.setHour(10); energencyProjects.writeProgram(); energencyProjects.setHour(12); energencyProjects.writeProgram(); energencyProjects.setHour(13); energencyProjects.writeProgram(); energencyProjects.setHour(14); energencyProjects.writeProgram(); energencyProjects.setHour(17); energencyProjects.writeProgram(); energencyProjects.setWorkFinished(false); energencyProjects.writeProgram(); energencyProjects.setHour(19); energencyProjects.writeProgram(); energencyProjects.setHour(22); energencyProjects.writeProgram(); } }
注:本文内容源自程杰的《大话设计模式》
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。