状态模式(State Pattern)学习笔记

状态模式(State Pattern)学习笔记

1.为什么要使用状态设计模式`
如果一个对象总是处于几个已知状态中,并且当它处于不同的状态时,方法对应的行为不同。这时候使用状态设计模式较为合适。
对比使用if/else语句来解决这个问题,使用状态设计模式可以便于程序将来的设计和修改。
状态设计模式允许在运行时更改对象的行为或状态。每个行为都由一个状态类表示,并且该行为可以从一个状态更改为另一个状态。

2.如何尝试使用状态设计模式
大致思路是先写一个State接口,其他的状态都来实现这个接口。
关于这个State接口,好像也有些许的不同。
课上讲的方案是方案A

// 状态接口(方案A)
public interface State{
	State move(char c);
	boolean accept();
}

习题课中使用的方法是方案B

//状态接口(方案B)
public interface State {
 State parking();	//停车
 State depart();	//驶离
}

这两种方案有何不同呢

我个人感觉第二种方法比较直观,因为一看到方法的名字就可以知道它会转移到什么状态。在后续的操作中也可以直接调用对应的方法。相比于此,方法一就有一个明显的缺点,要转移到不同的状态就需要输入不同的字符型变量,显然不如第一个方法直观,可能会更容易出现拼写错误,程序员阅读起来可能也较为困难,需要更多的注释来补充帮助阅读。

我个人是倾向于在编程中使用第二种方法的,因为它看起来很直观,编写的时候思路会很清晰(比较适合经常写着写着就懵了的我…)。但是第二种方法也有它的缺点,例如:在状态较多时,由于每一个状态都要对应一个转移的方法,就会产生很多方法,但是实际上在状态中能调用的方法只有几个,很多方法的处理是抛出IllegalArgumentException,代码会很不美(可能一看就是菜鸟程序员)。而且这种做法可能违反LSP原则。

不过在Lab3的实验中我还是使用了方案二(本来就是菜鸟程序员),Lab3的内容是开发一套可复用的ADT实现。其中的状态转换图包括下面两个:
在这里插入图片描述这两个状态转移图的区别是,上方的状态转移图是可阻塞(block)的,而下面的状态转移图是不可阻塞的。

因此State的接口就应该包括以下这些方法:
①allocate(从waiting转移到allocated)
②startup(从allocated/blocked转移到running)
③cancel(从waiting/allocated/blocked转移到cancelled)
④block(从runing转移到block)
⑤complete(从running转移到ended)

因此State接口:

public interface State {
 State allocate();
 State startup();
 State cancel();
 State complete();
 State block();
}

按照前面的思路,它的具体实现也就很简单了,以WAITING状态为例


public class WAITING implements State{
 static State instance = new WAITING();
 private WAITING() {};
  
 @Override
 public State allocate() {
  return ALLOCATED.instance;
 }
 
 @Override
 public State startup() {
  throw new IllegalArgumentException();
 }
  @Override
 public State cancel() {
  return CANCELLED.instance;
 }
 
 @Override
 public State complete() {
  throw new IllegalArgumentException();
 }
 
 @Override
 public State block() {
  throw new IllegalArgumentException();
 }
 
 public static State getState() {
  return instance;
 }
 
 @Override
 public String toString() {
  return "WAITING";
 }  
 
}

具体使用时,只需要用try-catch语句就可以完成状态的转移

 private State state = WAITING.getState();
 public boolean startup() {
  try{
   state = state.startup();
   return true;
  }catch(IllegalArgumentException IAE) {
   return false;
  }
 }

至此就完成了状态模式的初次使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值