定义:
对于有状态的对象,把复杂的“判断逻辑”提取到不同的对象中,允许状态对象在其内部状态发生改变时改变其行为。
适用场景:
1、当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为时,就可以考虑使用状态模式。
2、一个操作中含有庞大的分支结构,并且这些分支决定于对象的状态时。
优点:
1、状态模式将与特定状态相关的行为局部化到一个状态中,并且将不同状态的行为分割开来,满足“单一职责原则”。
2、减少对象间的相互依赖。将不同的状态引入独立的对象中会使得状态转换变得更加明确,且减少对象间的相互依赖。
3、有利于程序的扩展。通过定义新的子类很容易地增加新的状态和转换。
缺点:
1、状态模式的使用必然会增加系统的类与对象的个数。
2、状态模式的结构与实现都较为复杂,如果使用不当会导致程序结构和代码的混乱。
组成元素:
1、环境(Context)角色:也称为上下文,它定义了客户端感兴趣的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
2、抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
3、具体状态(Concrete State)角色:现抽象状态所对应的行为。
类图如下:
抽象代码示例:
1、定义环境角色Context:
public class Context {
public State state;
public Context(State state){
this.state=state;
}
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
public void Handle(){
state.Handle(this);
}
}
2、定义抽象状态角色State:
public interface State {
public void Handle(Context context);
}
3、定义具体状态角色ConcreteStateA和ConcreteStateB:
public class ConcreteStateA implements State{
@Override
public void Handle(Context context) {
System.out.println("当前状态是 A.");
context.setState(new ConcreteStateB());
}
}
public class ConcreteStateB implements State{
@Override
public void Handle(Context context) {
System.out.println("当前状态是 B.");
context.setState(new ConcreteStateA());
}
}
4:测试代码如下:
public class TestMain {
public static void main(String[] args) {
Context context = new Context(new ConcreteStateA());
context.Handle();
context.Handle();
context.Handle();
context.Handle();
}
}
5:输出结果如下:
示例代码分析:
接下来我们用“状态模式”设计一个学生成绩的状态转换程序,本实例包含了“不及格”“中等”和“优秀” 3 种状态,当学生的分数小于 60 分时为“不及格”状态,当分数大于等于 60 分且小于 90 分时为“中等”状态,当分数大于等于 90 分时为“优秀”状态,我们用状态模式来实现这个程序。
1、定义分数环境ScoreContext:
public class ScoreContext {
private AbstractState state;
public 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);
}
}
2、定义抽象状态AbstractState:
public 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);
}
}
3、定义三个具体的状态不及格状态LowState、中等状态MiddleState、优秀状态HighState:
public class LowState extends AbstractState{
public LowState(ScoreContext h) {
hj=h;
stateName="不及格";
score=0;
}
public LowState(AbstractState state) {
hj=state.hj;
stateName="不及格";
score=state.score;
}
@Override
public void checkState() {
if(score>=90){
hj.setState(new HighState(this));
}else if(score>=60){
hj.setState(new MiddleState(this));
}
}
}
public class MiddleState extends AbstractState{
public MiddleState(AbstractState state) {
hj=state.hj;
stateName="中等";
score=state.score;
}
@Override
public void checkState() {
if(score<60){
hj.setState(new LowState(this));
}else if(score>=90){
hj.setState(new HighState(this));
}
}
}
public class HighState extends AbstractState{
public HighState(AbstractState state) {
hj=state.hj;
stateName="优秀";
score=state.score;
}
@Override
public void checkState() {
if(score<60){
hj.setState(new LowState(this));
}else if(score<90){
hj.setState(new MiddleState(this));
}
}
}
4、测试代码如下:
public class TestMain {
public static void main(String[] args) {
ScoreContext account=new ScoreContext();
System.out.println("学生成绩状态测试:");
account.add(30);
account.add(40);
account.add(25);
account.add(-15);
account.add(-25);
}
}
5、输出代码如下: