前言
Lab3中需要使用状态模式来控制一个计划项的运行状态,并且在五个应用中总共有两类状态转换图(状态机)。因为有一些状态是重叠的,因此可以将他们共享,二选一,我采用布尔变量控制,但是状态模式的基本“套路”还是没有变的。
模式结构
状态模式包含以下主要角色。
- 环境(Context)角色:也称为上下文,它定义了客户感兴趣的接口,维护一个当前状态,并将与状态相关的操作委托给当前状态对象来处理。
- 抽象状态(State)角色:定义一个接口,用以封装环境对象中的特定状态所对应的行为。
- 具体状态(Concrete State)角色:实现抽象状态所对应的行为。
可以结合具体代码对照,State实际上被定义为一个抽象类,这个抽象类中应该包括状态机中各种状态的一些共有属性,比如“状态名”。
Concrete State 对应位State的一些具体实现类,来定义状态机中所需要的状态类。
而环境Context,不如说是状态机,前两者提供了这个“机器”的一些零件,但实际的运转却需要将这些零件组合起来。
你也可以看到,具体类的创建(或者说状态转换的一个操作)是直接new 一个对应的状态类的,这个有点像工厂模式。
代码中的状态转换图:
package Resource;
//状态机
public class StateMachine
{
private State state;
private boolean type;//true代表第二种
//构造函数,初始为wait
public StateMachine(boolean type)
{
state=new WAITING();
// System.out.println(state.stateName);
this.type=type;
}
public void setState(State state)
{
this.state=state;
}
public State getState()
{
return state;
}
public String getStateName(){
return state.stateName;
}
public boolean allocate()
{
if(state.stateName.equals("未分配状态")){
((WAITING) state).allocate(this);
// System.out.println(state.stateName);
return true;
}else
return false;
}
public boolean run()
{
if(state.stateName.equals("已分配状态")){
((ALLOCATED) state).run(this);
// System.out.println(state.stateName);
return true;
}else
return false;
}
public boolean block()
{
if(this.type)
return false;
if(state.stateName.equals("运行状态")){
((Running) state).suspend(this);
// System.out.println(state.stateName);
return true;
}else
return false;
}
public boolean end()
{
if(state.stateName.equals("运行状态")){
((Running) state).stop(this);
// System.out.println(state.stateName);
return true;
}else
return false;
}
public boolean resume()
{
if(this.type)
return false;
if(state.stateName.equals("挂起状态")){
((Blocked) state).resume(this);
// System.out.println(state.stateName);
return true;
}else
return false;
}
public boolean cancel()
{
switch (state.stateName) {
case "未分配状态":
((WAITING) state).cancel(this);
// System.out.println(state.stateName);
return true;
case "已分配状态":
((ALLOCATED) state).cancel(this);
// System.out.println(state.stateName);
return true;
case "挂起状态":
((Blocked) state).cancel(this);
// System.out.println(state.stateName);
return true;
default:
// System.out.println(state.stateName);
// System.out.println("当前状态不可调用cancel()");
return false;
}
}
}
//抽象状态类:状态
abstract class State
{
protected String stateName; //状态名
}
//具体状态类:未分配状态
class WAITING extends State
{
public WAITING()
{
stateName="未分配状态";
}
//申请资源分配
public void allocate(StateMachine hj)
{
if(stateName.equals("未分配状态"))
{
hj.setState(new ALLOCATED());
}
else
{
System.out.println("当前线程不是未分配状态,不能调用allocate()方法.");
}
}
//取消
public void cancel(StateMachine hj)
{
if(stateName.equals("未分配状态"))
{
hj.setState(new CANCELLED());
}
else
{
System.out.println("当前线程不是未分配状态,不能调用cancel()方法.");
}
}
}
//具体状态类:已分配状态
class ALLOCATED extends State
{
public ALLOCATED()
{
stateName="已分配状态";
}
public void run(StateMachine hj)
{
if(stateName.equals("已分配状态"))
{
hj.setState(new Running());
}
else
{
System.out.println("当前线程不是已分配状态,不能调用run().");
}
}
public void cancel(StateMachine hj)
{
if(stateName.equals("已分配状态"))
{
hj.setState(new CANCELLED());
}
else
{
System.out.println("当前线程不是已分配状态,不能调用cancel()方法.");
}
}
}
//具体状态类:运行状态
class Running extends State
{
public Running()
{
stateName="运行状态";
}
public void suspend(StateMachine hj)//阻塞
{
if(stateName.equals("运行状态"))
{
hj.setState(new Blocked());
}
else
{
System.out.println("当前线程不是运行状态,不能调用suspend()方法.");
}
}
public void stop(StateMachine hj)//结束
{
if(stateName.equals("运行状态"))
{
hj.setState(new ENDED());
}
else
{
System.out.println("当前线程不是运行状态,不能调用stop()方法.");
}
}
}
//具体状态类:挂起状态
class Blocked extends State
{
public Blocked()
{
stateName="挂起状态";
}
public void resume(StateMachine hj)//恢复运行
{
if(stateName.equals("挂起状态"))
{
hj.setState(new Running());
}
else
{
System.out.println("当前线程不是挂起状态,不能调用resume()方法.");
}
}
public void cancel(StateMachine hj)
{
if(stateName.equals("挂起状态"))
{
hj.setState(new CANCELLED());
}
else
{
System.out.println("当前线程不是挂起状态,不能调用cancel()方法.");
}
}
}
//具体状态类:已完成状态
class ENDED extends State
{
public ENDED()
{
stateName="已完成状态";
}
}
//具体状态类:已取消状态
class CANCELLED extends State
{
public CANCELLED()
{
stateName="已取消状态";
}
}
之后再讨论提到的工厂设计模式,其实从这章要讲的程序的可维护性和复用性来看,讲到的设计模式其实都要符合LSP原则,还是比较容易理解的,但是对于这次实验的具体内容来说,有些地方用设计模式反而变复杂了(虽然有些设计模式本身继承树就很深),而且也存在一些矛盾的地方,之后想到哪再说说吧。