【图解设计模式系列】The State Pattern: 状态模式
1 allows an object to alter its behavior when its internal state changes. The object will appear to change its class.
2 The State Pattern has the same class diagram as The Strategy Pattern, but they differ in intent.
看了上面两行狗屁不通的抽象话
状态模式也称状态机(State Machine),简单用一句话解释就是:用对象定义具体状态,调用时指向具体状态对象的方法。
还是很抽象,看看下面状态模式包含的角色
状态模式包含以下主要角色。
- 环境(Context)角色:也称为上下文,它定义了客户感兴趣的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
- 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
- 具体状态(Concrete State)角色:实现抽象状态所对应的行为。

说了这些 还是屁都不懂,不如看实例和代码来的直接。
实例
用“状态模式”设计一个学生成绩的状态转换程序。包含了“不及格”“中等”和“优秀” 3 种状态,当学生的分数小于 60 分时为“不及格”状态,当分数大于等于 60 分且小于 90 分时为“中等”状态,当分数大于等于 90 分时为“优秀”状态,我们用状态模式来实现这个程序。(抽象出来就是某个类有有限个状态,应该用状态模式 那怎么写呢?)
看下面的代码 大体意思就是说 我们把状态抽象出来,写个抽象状态类。然后我们把那几个具体状态也分别写实体类。虽然这样听上去很麻烦 但是实际上 可以极大的方便我们增加新的状态
package state;
public class ScoreStateTest
{
public static void main(String[] args)
{
ScoreContext account=new ScoreContext();
System.out.println("学生成绩状态测试:");
account.add(30);
account.add(40);
account.add(45);
account.add(-35);
account.add(-25);
}
}
//环境类 === 定义
class ScoreContext
{
private AbstractState state;
ScoreContext()
{
state=new LowState(this);
}
public void setState(AbstractState state)
{
this.state=state;
}
public AbstractState getState()
{
return state;
}
public void add(int score)
{
state.addScore(score);
}
}
//抽象状态类 ====抽象类 定义各种状态
abstract class AbstractState
{
protected ScoreContext hj; //环境
protected String stateName; //状态名
protected int score; //分数
public abstract void checkState(); //检查当前状态
public void addScore(int x)
{
score+=x;
System.out.print("加上:"+x+"分,\t当前分数:"+score );
checkState();
System.out.println("分,\t当前状态:"+hj.getState().stateName);
}
}
//具体状态类:不及格
class LowState extends AbstractState
{
public LowState(ScoreContext h)
{
hj=h;
stateName="不及格";
score=0;
}
public LowState(AbstractState state)
{
hj=state.hj;
stateName="不及格";
score=state.score;
}
public void checkState()
{
if(score>=90)
{
hj.setState(new HighState(this));
}
else if(score>=60)
{
hj.setState(new MiddleState(this));
}
}
}
//具体状态类:中等
class MiddleState extends AbstractState
{
public MiddleState(AbstractState state)
{
hj=state.hj;
stateName="中等";
score=state.score;
}
public void checkState()
{
if(score<60)
{
hj.setState(new LowState(this));
}
else if(score>=90)
{
hj.setState(new HighState(this));
}
}
}
//具体状态类:优秀
class HighState extends AbstractState
{
public HighState(AbstractState state)
{
hj=state.hj;
stateName="优秀";
score=state.score;
}
public void checkState()
{
if(score<60)
{
hj.setState(new LowState(this));
}
else if(score<90)
{
hj.setState(new MiddleState(this));
}
}
}
优缺点
优点:
封装了转换规则。枚举可能的状态,在枚举状态之前需要确定状态种类。
将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
允许状态转换逻辑与状态对象合成一体,而不是某一个巨大的条件语句块。
可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点:
状态模式的使用必然会增加系统类和对象的个数。
状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
状态模式对“开闭原则”的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态;而且修改某个状态类的行为也需修改对应类的源代码。

浙公网安备 33010602011771号