设计模式之状态模式
替换繁琐if else和多状态转换
- 概念
- 使用场景
- 类图
- 代码实例
概念
一个对象中存在多种状态,并且不同的状态下对象有不同的行为操作,传统的实现方式就是if else 分支条件就是不同的状态,分支内容就是对应状态下的操作。 如果对象仅仅有一两个状态,不复杂还行。当状态很多且状态转换很复杂时就需要考虑使用状态模式
状态模式:抽象出一个状态接口,if else分支中的条件对应不同的状态子类,将相应状态下操作逻辑放在对应的状态类中(迁移到下个状态 其下个状态是确定的),状态类之间互不影响。 符合开闭原则,当需要增加一个状态时,只需要增加一个类,并实现相应的逻辑。
使用场景
状态模式适用于某一个对象的行为取决于该对象的状态,并且该对象的状态会在运行时转换,又或者有很多的if else判断,而这些判断只是因为状态不同而不断的切换行为。
类图
Work:相当于Context上下文类,里面包含了抽象状态类(工作状态)
WorkState:抽象工作状态
ForenoonState:上午工作状态 具体的工作状态类,实现接口的方法,该方法就是相当于传统使用if else实现的分支里的内容,并且在其方法内容做状态的转换
HavingLunchState:用餐状态
LunchRestState:午休状态
AfternoonState:下午工作状态
Client:客户端测试,只依赖于Work类进行相应的操作
代码实例
背景:
一个人随着时间改变工作状态也会随之改变,上午工作状态饱满,中午工作状态不行饿了要吃饭,午休时间要睡会觉,下午工作状态饱满,再则进入晚间工作状态,如果没有干完活就需要加班了,到了22点就进入睡眠。
以上场景很常见都是每个人亲身经历过的,根据上面分析出 随着一天当中时间推移,工作者会进入不同的状态,下面我会用传统方式和状态模式实现,可以体会到状态模式的好处。上面可以分出以下几种状态 上午工作状态、中午工作状态、午休工作状态、下午工作状态、晚间工作状态、睡眠状态、下班休闲状态
WorkByTradition 使用传统 if else实现的方式
/**
* @author duanyimiao
* @create 2018-10-09 10:38 AM
* @description 工作类 使用if else实现
**/
public class WorkByTradition {
//工作时的钟点
private Integer hour;
//工作是否完成
private Boolean isFinished;
public static void main(String[] args) {
}
/**
* 重构这本书说到,Long Method很长的一个方法肯定不符合单一职责原则,很多if else语句维护性极差,例如公司有个政策说所有员工在18点之后都要回家不加班,这个时候就需要进行改动,一不小心就会改错了。这些工作对象状态随时间改变而改变,进而产生不同的行为操作,接下来会使用状态模式进行重构。
*/
public void writeProgram() {
if (hour < 12) {
System.out.println("上午开始工作,精神状态倍佳" + hour);
} else if (hour < 13) {
System.out.println("肚子咕咕叫,进入用餐时间" + hour);
} else if (hour < 14) {
System.out.println("午休十分钟,精神一下午");
} else if (hour < 18) {
System.out.println("下午精神饱满,继续努力");
} else if (hour < 21) {
if (isFinished) {
//今天的工作完成了
System.out.println("go home for having a rest");
} else {
System.out.println("加班中");
}
} else if (hour < 22) {
System.out.println("太累了,睡着了 sleep");
}
}
public Integer getHour() {
return hour;
}
public void setHour(Integer hour) {
this.hour = hour;
}
public Boolean getFinished() {
return isFinished;
}
public void setFinished(Boolean finished) {
isFinished = finished;
}
}
WorkState 抽象工作状态
/**
* @author duanyimiao
* @create 2018-10-09 3:25 PM
* @description 抽象工作状态
**/
public interface WorkState {
/**
* 在某状态下的行为操作
* @param work
*/
void writeProgram(Work work);
}
ForenoonState 上午工作状态
/**
* @author duanyimiao
* @create 2018-10-09 3:30 PM
* @description 上午状态
**/
public class ForenoonState implements WorkState {
/**
* 在上午状态下写代码
*
* @param work Work上下文
*/
@Override
public void writeProgram(Work work) {
if (work.getHour() < 12) {
System.out.println("上午开始工作,精神状态倍佳" + work.getHour());
} else {
work.setWorkState(Work.HAVINGLUNCH_STATE);
work.writeProgram();
}
}
}
HavingLunchState 午餐状态
/**
* @author duanyimiao
* @create 2018-10-09 3:30 PM
* @description 午餐状态
**/
public class HavingLunchState implements WorkState {
/**
* @param work Work上下文
*/
@Override
public void writeProgram(Work work) {
if (work.getHour() < 13) {
System.out.println("肚子咕咕叫,进入用餐时间" + work.getHour());
} else {
work.setWorkState(Work.LUNCHREST_STATE);
work.writeProgram();
}
}
}
LunchRestState 午休状态
/**
* @author duanyimiao
* @create 2018-10-09 3:30 PM
* @description 午休状态
**/
public class LunchRestState implements WorkState {
/**
* @param work Work上下文
*/
@Override
public void writeProgram(Work work) {
if(work.getHour() < 14) {
System.out.println("午休十分钟,精神一下午");
}else{
work.setWorkState(Work.AFTERNOON_STATE);
work.writeProgram();
}
}
}
AfternoonState 下午工作状态
/**
* @author duanyimiao
* @create 2018-10-09 3:30 PM
* @description 下午工作状态
**/
public class AfternoonState implements WorkState {
/**
* @param work Work上下文
*/
@Override
public void writeProgram(Work work) {
if (work.getHour() < 18) {
System.out.println("下午精神饱满,继续努力");
} else {
work.setWorkState(Work.EVENING_STATE);
work.writeProgram();
}
}
}
EveningState 晚间工作状态
/**
* @author duanyimiao
* @create 2018-10-09 3:30 PM
* @description 晚间工作状态
**/
public class EveningState implements WorkState {
/**
* @param work Work上下文
*/
@Override
public void writeProgram(Work work) {
if (work.getFinished()) {
work.setWorkState(Work.REST_STATE);
work.writeProgram();
}else {
if(work.getHour() < 21) {
System.out.println("加班中");
}else {
work.setWorkState(Work.SLEEP_STATE);
work.writeProgram();
}
}
}
}
RestState 下班休息状态
/**
* @author duanyimiao
* @create 2018-10-09 3:30 PM
* @description 下班休息状态
**/
public class RestState implements WorkState {
/**
* @param work Work上下文
*/
@Override
public void writeProgram(Work work) {
System.out.println("go home for having a rest");
}
}
SleepState 睡觉状态
/**
* @author duanyimiao
* @create 2018-10-09 3:30 PM
* @description 睡觉状态
**/
public class SleepState implements WorkState {
/**
* @param work Work上下文
*/
@Override
public void writeProgram(Work work) {
System.out.println("太累了,睡着了 sleep");
}
}
Work 工作类
/**
* @author duanyimiao
* @create 2018-10-09 3:25 PM
* @description 工作类(Context上下文类)
**/
public class Work {
public static final WorkState FORENOON_STATE = new ForenoonState();
public static final WorkState HAVINGLUNCH_STATE = new HavingLunchState();
public static final WorkState LUNCHREST_STATE = new LunchRestState();
public static final WorkState AFTERNOON_STATE = new AfternoonState();
public static final WorkState EVENING_STATE = new EveningState();
public static final WorkState REST_STATE = new RestState();
public static final WorkState SLEEP_STATE = new SleepState();
//工作时的钟点
private Integer hour;
//工作是否完成
private Boolean isFinished = false;
//工作状态
private WorkState workState;
public Work() {
workState = FORENOON_STATE;
}
public void writeProgram() {
workState.writeProgram(this);
}
public Integer getHour() {
return hour;
}
public void setHour(Integer hour) {
this.hour = hour;
}
public Boolean getFinished() {
return isFinished;
}
public void setFinished(Boolean finished) {
isFinished = finished;
}
public WorkState getWorkState() {
return workState;
}
public void setWorkState(WorkState workState) {
this.workState = workState;
}
}
Client 客户端测试类
/**
* @author duanyimiao
* @create 2018-10-09 3:26 PM
* @description
**/
public class Client {
public static void main(String[] args) {
//WorkByTradition work = new WorkByTradition();
Work work = new Work();
work.setHour(10);
work.writeProgram();
work.setHour(13);
work.writeProgram();
work.setHour(15);
work.writeProgram();
work.setHour(22);
work.setFinished(true);
work.writeProgram();
}
}
输出结果
上午开始工作,精神状态倍佳10
午休十分钟,精神一下午
下午精神饱满,继续努力
go home for having a rest