享受代码,享受人生

SOA is an integration solution. SOA is message oriented first.
The Key character of SOA is loosely coupled. SOA is enriched
by creating composite apps.
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

从一个画图程序谈起---模式(3)

Posted on 2005-01-29 14:28  idior  阅读(1755)  评论(0编辑  收藏  举报

上文已经提到如何消除条件,通过多态,这是面向对象的显著特征之一。

在使用多态之前我们先把思路理理清楚。在这个程序中主要涉及了两个状态,以及在两个状态下发生的一些事件。我们用一个活动图把它形象的表示一下。


两个状态Get First PointGet Second Point,在第一个状态移动鼠标没有任何反应,不要做什么事也不会发生状态变迁。如果鼠标点击一下也就是GetPoint事件发生,那么我们的状态将发生变化,转至Get Second Point状态。图中的@RecondStartPt是指在GetPoint事件发生时所要做的事,即记录下第一个点,也就是线段的起点。在第二个状态下移动鼠标也不会发生状态变迁,但是需要处理DragLine,也就是实现直线的脱拽效果。此时如果点击鼠标,那会引起状态转移,转移到Get First Point,并记下第二个点也就是线段的终点。

我们发现在每个状态下,只有两个事件GetPointMovePoint RecordStartPt等等发生在他们之中),而每个状态的处理方法不同,从中可以明显看出多态的影子。

 

一个接口IUIState,包含两个方法GetPointMovePoint ,两个状态分别对应于两个具体实现类。


这就是一个典型的State模式的UML图(有关State模式,由于吕震宇的文章还没出来,就参考一下我的一片随笔吧),

MainForm中MovePointGetPoint,它自己什么也不作只是简单的委托给State来完成,(此处的delegateC#的那个delegate不是一个东西喔),MainForm只需要提供必要的UI操作的方法和状态变迁的方法供State使用。StateGetPointMovePoint事件处理中主要干两件事,一个做前面活动图中有@前缀的事,还有就是进行必要的状态转化。

这样我们的画图(其实就是画线)程序就完成了。采用了State模式完全解决了我在开头提出的3个缺点。而且还利于扩展,要有什么新的动作,也很方便实现。

但是目前的设计已经完美吗?没有。两个具体的State类竟然依赖于MainForm这个具体类,当然不合理了,根本就没法重用State这块了(蓝色区)。

所以我们要Design to interface,改成下面这个样子。




这样State这部分就不再依赖于具体了,以后让其他的Form实现ISateCallBack就可以使用State模式了,而且State模式部分根本不要改任何代码。(比如你不想在一个WindowsForm上画线,而是在自己的Canvas上作图。)

现在的State模式已经显的比较完美了,不过看到下面这段我也很不爽。


public void GetPoint(IStateCallBack i)
        
{
            
if (currentUIState != null)
            
{                currentUIState.GetPoint(i);
            }

        }


防御型语句我也不想看到。发挥一下State模式的威力吧,引入一个Null Object。


Null Object
顾名思义什么也不作,让那两个方法为空就行了。

这样我们就去掉了那个if,一切变的那么简单。

在这个框架的基础上要实现添加新的行为,你会发现条理很清晰(跟最初的比比),不如你把它完善吧。

 

(注:本文只是演示重构和模式的实例,在逻辑上不是那么的完备,如果你有兴趣可以把它完善.比如工作生活提出的bug.)

参考资料―――Agile software development


最终源代码下载