薛磊 Job Seeker

23种设计模式——21.State 状态 (行为型模式)


动机(Motivattion)

  在软件构建过程中,某些对象的状态如果改变,其行为也会随之而发生改变,比如电梯在运行和停止状态可以进行哪些操作,其支持的行为和运行/停止状态支持的行为就可能完全不同。

  如何在运行时根据对象的状态来透明地更改对象的行为?而不会为对象操作和状态转化之间引入紧耦合?

意图(Intent)

  允许一个对象在其内部状态改变时改变它的行为。从而使对象看起来似乎修改了其行为。

结构(Structure)

  • State:抽象状态角色  负责对象状态定义,并且封装环境角色以实现状态的切换

  • ConcreteState:具体状态角色  每个具体状态必须完成两个职责:本状态的行为管理以及趋向状态处理

  • Context:环境角色  定义客户端需要的接口,并且负责具体状态的切换,串联各个状态的过渡。

    State模式的几个要点

  • State模式将所有与一个特定状态相关的行为都放入一个State的子类对象中,在对象状态切换时,切换相应的对象;但同时维持State的接口,这样实现了具体操作与状态转换之间的解耦。

  • 为不同的状态引入不同的对象使得状态转换变得更加明确,而且可以保证不会出现状态不一致的情况,因为转换是原子性的——即要么彻底转换,要么不转换。

  • 如果State对象没有实例变量,那么各个上下文可以共享同一个State对象,从而节省对象开销。

  某一角色在在执行行为时,通过环境角色知道自己目前的状态,然后执行此状态下的行为或通过状态下的过渡方法转到其他状态。

实例代码

抽象状态角色:

public abstract class State{
	//定义一个环境角色,提供在子类访问
	protected Context context;
	//设置环境角色
	public void setContext(Context context){
		this.context = context;
	}
	//行为1
	public abstract void handle1();
	//行为2
	public abstract void handle2();
}

具体状态角色:

public class ConcreteState1 extends State{
	public void handle1(){
		//本状态下必须处理的逻辑
	}
	public  void handle2(){
		//设置当前状态为state2
		super.context.setState(Context.STATE2);
		//过渡到state2状态,由handle2();
	}
}

public class ConcreteState2 extends State{
	public  void handle1(){
		//设置当前状态为state1
		super.context.setState(Context.STATE1);
		//过渡到state1状态,由handle1();
	}
	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();
	}
}

场景类:

public class Client{
	public static void main(String[] args){
		//定义环境角色
		Context context = new Context();
		//初始化状态
		context.setCurrentState(new ConcreteState1);
		//行为执行
		context.handle1();
		context.handle2();
	}
}

Comments

Content