Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1740695
  • 博文数量: 438
  • 博客积分: 9799
  • 博客等级: 中将
  • 技术积分: 6092
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-25 17:25
文章分类

全部博文(438)

文章存档

2019年(1)

2013年(8)

2012年(429)

分类: C/C++

2012-03-25 19:22:18

有时候写程序时,你有没有碰到过要维护很多状态从而写很多条件判断(if...else...)语句?比如一个简单的开关,有“开”和“关”状态,按下开关可以切换这两个状态:
  1. void switch()
  2. {
  3.     if (state == ON)
  4.         state = OFF;
  5.     else
  6.         state = ON;
  7. }

如果它还分高中低三档,按一次开关可以在这几种状态中切换:
  1. void switch()
  2. {
  3.     if (state == OFF)
  4.         state = LOW;
  5.     else if (state == LOW)
  6.         state = MIDDLE;
  7.     else if (state == MIDDLE)
  8.         state = HIGH;
  9.     else if (state == HIGH)
  10.         state = OFF;
  11. }

如果以后设计改变,要让OFF状态直接跳到HIGH,而不是LOW,这个条件又要更改。至今为止还能接受,毕竟只有一个条件分支,咬咬牙也忍了。如果这个开关是按的,而是扭(旋转)呢?左旋让状态由高到低,而右旋让状态由低到高。
  1. void rotateRight()
  2. {
  3.     if (state == OFF)
  4.         state = LOW;
  5.     else if (state == LOW)
  6.         state = MIDDLE;
  7.     else if (state == MIDDLE)
  8.         state = HIGH;
  9.     else if (state == HIGH)
  10.         state = OFF;
  11. }

  12. void rotateLeft()
  13. {
  14.     if (state == OFF)
  15.         state = HIGH;
  16.     else if (state == HIGH)
  17.         state = MIDDLE;
  18.     else if (state == MIDDLE)
  19.         state = LOW;
  20.     else if (state == LOW)
  21.         state = OFF;
  22. }

如果有这样两个动作,以后设计改变时,想把三档改成五档,就要同时改动rotateLeft和rotateRight,当状态变得很多时,代码就变得极容易出错。如果一个设计有更多的动作时(rotateLeft就是一个动作),状态的改变会变得很难维护。

如果把每个状态都抽取出来作为一个类呢?


  1. interface State
  2. {
  3.     virtual State* rotateLeft() = 0;
  4.     virtual State* rotateRight() = 0;
  5. };

简化描述,只考虑On和Off的状态:
  1. class OnState : State
  2. {
  3. public:
  4.     virtual State* rotateLeft() { return new OffState; }
  5.     vritual State* rotateRight() { return new OffState; }
  6. };

  7. class OffState : State
  8. {
  9. public:
  10.     virtual State* rotateLeft() { return new OnState; }
  11.     vritual State* rotateRight() { return new OnState; }
  12. };

对于client这边就以简化它的逻辑了:
  1. class Client
  2. {
  3.     void rotateLeft() { this->state = this->state->rotateLeft(); }
  4.     void rotateRight() { this->state = this->state->rotateRight(); }
  5. };

以后状态的增加或改变都不需要影响Client的代码。而且因为没有了繁琐的条件语句,代码也变得好维护了。

状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。

状态模式与策略模式的比较:

这两种模式在类图上看是基本相同的:客户拥有一个接口(状态或策略),当有新的状态或策略加入时,其必须实现这个接口。客户则只需直接对这个接口操作,而不用管那些实现了接口的具体状态或策略。

两种模式的区别在于:策略模式偏重于行为,每个新加入的类都描述了一个算法;而状态模式偏向于状态,每个新加入的类描述了一个状态。
阅读(829) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~