设计模式之禅笔记——状态模式
一、状态模式的定义
Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.(当一个对象的状态改变时允许其改变行为,这个对象看起来像改变了其类)
状态模式的核心是封装,状态的变更引起了行为的变更,从外部看来就好像这个对象对ing的类发生了改变了一样,状态模式的通用类图如下:
State——抽象状态角色:接口或抽象类,负责对象状态定义,并且封装环境角色以实现状态切换
ConcreteState——具体状态角色:每一个具体状态必须完成两个职责,本状态的行为管理以及趋向状态处理,通俗的说,就是本状态下要做的事情,以及本状态如何过渡到其他状态
Context——环境角色:定义客户端所需要的接口,并且负责具体状态的切换
抽象环境角色代码:
public abstract class State {
protected Context context;
public void setContext(Context context) {
this.context = context;
}
public abstract void handle1();
public abstract void handle2();
}
环境角色代码:
public class ConcreteState1 extends State {
@Override
public void handle1() {
//本状态下必须处理的逻辑
}
@Override
public void handle2() {
//设置当前状态为state2
super.context.setCurrentState(Context.STATE2);
//过度到state2状态,由Context实现
super.context.handle2();
}
}
public class ConcreteState2 extends State {
@Override
public void handle1() {
//设置当前状态为state1
super.context.setCurrentState(Context.STATE1);
//过度到state1状态,由Context实现
super.context.handle1();
}
@Override
public void handle2() {
//本状态下必须处理的逻辑
}
}
具体环境角色
public class Context {
//定义状态
public final static State STATE1 = new ConcreteState1();
public final static State STATE2 = new ConcreteState2();
//当前状态
private State currentState;
//获取当前状态
public State getCurrentState() {
return currentState;
}
//设置当前状态
public void setCurrentState(State currentState) {
this.currentState = currentState;
//切换状态
this.currentState.setContext(this);
}
//行为委托
public void handle1() {
this.currentState.handle1();
}
public void handle2() {
this.currentState.handle2();
}
}
环境角色有两个不成文的约束:
1、把状态对象声明为静态常量有几个状态就声明几个静态常量
2、环境角色具有状态抽象角色定义的所有行为,具体执行使用委托模式
具体环境角色:
public class Client {
public static void main(String args[]) {
//定义环境角色
Context context = new Context();
//初始化状态
context.setCurrentState(new ConcreteState1());
//行为执行
context.handle1();
context.handle2();
}
}
二、状态的优缺点和使用场景
优点:
结构清晰:避免了过多的switch...case 或者if...else语句的使用,避免了程序的复杂性,提高系统的可维护性。
遵循设计原则:很好的体现了开闭原则和单一职责,每个状态都是一个子类,你要增加状态就增加子类,你要修改状态,你只修改一个子类就可以了。
封装性非常好:这也是状态模式的基本要求,状态变换放置到类的内部实现,外部的调用不用知道类内部如何实现状态的切换和行为的变换。
缺点:
状态模式既然有优点,那当然有缺点了。但只有一个缺点,子类会太多,也就是类膨胀,如果一个事物有很多状态也不稀奇,如果完全使用状态模式会有太多的子类,不好管理,这个需求大家在项目中自己衡量。其实有很多方式可以解决这个状态问题,如在数据库中建立一个状态表,然后根据状态执行相应的操作
使用场景:
行为随状态改变而改变的场景:这也是状态模式的根本出发点,例如权限设计、人员的状态不同即使执行相同的行为结果也会不同在这种情况下需要考虑使用状态模式
条件、分支判断语句的替代者:在程序中大量使用switch语句或if判断语句会导致程序结构不清晰,逻辑混乱,使用状态模式可以很好的避免这一问题,它通过扩展子类实现了条件的判断处理。
上一篇: ganglia集群监控系统_使用Ganglia监控企业集群
下一篇: 状态模式