State模式技术交流后感

类别:软件工程 点击:0 评论:0 推荐:
1       缘起

       2004年5月19日,部门在大厦2号楼9楼大会议室举行有关OO设计思想以及优秀开发工具的技术交流活动。会上,同事<隐去其名字>主讲了两个主题的内容,分别是“State模式”以及“Dunit单元测试工具”。在前一个主题的讲座和技术交流过程中,大家进行了比较充分的讨论。我本人也有一些感想和心得,特此记录,以飨读者。

 

2       场景

       以十字转门为例。

       以上是十字转门的状态迁移图(采用UML)。该图的格式具有如下特点:

1.       采用圆角矩形表达可能的所有状态。注意,状态应该采用形容词表达;

2.       使用单箭头的线段表达迁移,迁移由原状态指向目的状态。迁移线段上的文字包含事件和动作两个部分,并使用”/”分割。

综合上图可知:

n         十字转门共有两个状态,分别为Locked以及Unlocked;

n         十字转门共有两种事件,分别为Pass和Coin。

n         通过各个状态对事件的处理,可以得到四种动作,分别为SetLocked,SetUnLocked,Alarm,Thank you。其中,Alarm以及Thank you可看作是对于异常情况的处理。

 

3       初步实现

       简单考虑之后,采用Case来实现以上功能,如:

    Tstate = (stLocked, stUnLocked);

    TeventType = (etPass, etCoin);

    …

    case Fstate of

        stLocked:

            case AeventType of

                etPass:

                    DoAlarm;

                etCoin:

                    DoSetUnLocked;

        stUnLocked:

            case AeventType of

                etPass:

                    DoSetLocked;

                etCoin:

                    DoThankYou;

        end;

       可以看到,以上代码通过Case语句的层次嵌套完成了功能。功能尽管已经实现,但我们心里似乎有些不够痛快——是否太繁琐了些?试想如果状态更多,事件也更多,那相应的case语句岂非要写的更长?而且不同状态对不同事件的处理代码集中在一起,造成了不必要的相关性,同时也给代码维护造成了更多笔误的机会(不可否认,逻辑集中也有其好处:阅读代码时方便)。

 

4       模式实现

       上述问题改用State模式来实现,那就是另一种风格和境界了:

       仔细研究上述图,不难发现:

1.  门类(TTurnstile)指向了一个代表其状态的一个具体状态类;

2.  把状态进行抽象,并将所有的事件作为抽象(纯虚)方法,然后为每个状态定义派生类来处理各个事件;

3.  相识关系:门类知道状态抽象类,以及所有的具体状态类;具体状态类没有成员变量,也不知道门类。具体状态类互相不相识;具体状态类仅仅从覆盖方法的参数中知晓当时所对应的门类的实例;

4.  每个具体的状态类可以采用单件方式(Singleton)实现;

上述解决方案的优势体现在:

1.  将状态和控制分开,两条线独立演化,系统的扩展性增强;

2.  状态之间互相不知晓,降低它们的耦合度;

3.  采用类名称以及事件名称,消除了原先的两层Case语句。

另外一个值得思考的问题:

状态的转换和动作的执行应该由谁来完成?在本例中,我认为状态类应该对此负责。因为如果由门类来完成,则该模式的应用就没有真正到位。

门类的职责:存储当前状态;转发事件;执行开门/关门动作;根据要求切换状态;

状态的真正切换还是由状态类来触发——从这个意义上来说,状态之间还是具有一定程度的耦合的——只是这种耦合不是直接的引用关系的耦合,而是通过逻辑关系进行的。

 

5       有关模式

模式是针对特定情况,适合解决特定场景下的特定问题的。一般而言,模式总能带来比较多的好处,但同时,也往往会带来一些缺陷或遗憾。如何取舍,要具体问题具体分析。其宗旨是如何让软件系统扩展性更好、可维护性更好,简单,容易理解。

 

6       其他 6.1   有关数据库持久化框架

本文地址:http://com.8s8s.com/it/it36880.htm