Fork me on GitHub
一个简单的领域模型的建模过程

一个简单的领域模型的建模过程

系统需求来源于一套大型系统的一小部分。
基本需求是:
用户选择图片文件,系统一系列验证(文件大小,数量,格式等)后,压缩,发送。
并记录发送结果。
通过需求分析得知,这个用例里面,除了用户需要向系统输入文件外,
剩下的工作都是系统来做,系统要经过一系列的步骤来完成指定任务。
所以这是一个工作流的问题,我们得到下面这个模型:

这是维持一个指向自身的链,通过Next可以访问链中的下一个节点。

其代码的实现大致如下:

复制代码
 public abstract class Processer
    {
        protected Processer next;
        protected abstract bool process();
        private List<Image> images;
public void Run() { bool r = process(); if (next != null) { if (r == true) { next.Run(); } } } }
复制代码

这只是建模了一个链的模型,下面是根据我们的需求添加具体的链节点,通过需求描述发现,我们需要“验证”、“压缩”、“发送”等具体的处理。所以模型应该是这样:

我们从一个链模型继承了三个具体的链节点,用来处理“检查”、“压缩”、“发送”的具体工作。从模型上我们能看出来,当需要新的处理要求出现时,我们仅需要继承一个新的处理节点,比如发送前需要“加密”,那么我们进需要在继承一个新的类:encryptor即可。

其实真正的系统中还有一个必须添加到节点,那就是处理持久化的相关工作。我们应该再继承一个新的类:DBAccesser。

通过分析我们发现,我们的这一设计在增加处理链的方向上满足了OCP原则。
作为一个设计洁癖(当然这不是一个好习惯)者,我发现Checker类有一些另我不安。
因为他一个人干了好几件事儿(大小检查,数量检查,格式检查),那么如果增加新的检查项目,势必需要修改Checker类,这不符合我刚刚提到的OCP原则。所以我决定把Checker的职责分开,得到下面的模型。

这样增加新的检查类型,只需要继承新的Checker即可,这又一次符合了OCP。
上面的模型暂时看一切顺利,那么下一步就是考虑一下UI的问题了。
我们重点考虑一下处理结果向UI反馈的问题。因为链是封闭式处理的,每个链节点处理的结果如果反馈给UI呢?最简单的方法就是每个节点都生成一个记录处理结果的对象,模型如下:

这是一个简单而直接的设计。当然正在的项目这么做也许就足够了。理论上细究起来,他存在一个问题,就是UI代码直接依赖于CheckerResult,CompressResult,SendResult这些具体的类,这样的设计不符合DIP原则,最直接的影响就是如果新追加节点,比如Encryptor,这个节点会产生一个处理结果对象,类型为:EncryptResult,UI为了反映这一个节点的处理结果。需要手动更改代码以添加对EncryptResult类的对象的访问。

老办法,看看添加一个接口好不好用:

通过添加一个IResult接口,这样每一个节点下的蛋(处理结果)都是同一类型了,在ResultProcessor类里可以统一处理每个节点的处理结果。

如果在进一步,可以把ResultProcessor变成一个接口,由具体的类来做具体的处理工作。

上面的模型看上去完全符合OCP,DIP,SRP这上个主要的设计原则。只是在创建处理链的代码中,可能有些不爽,
这个简单,抽象工厂好了,世人皆知的处理方法:

 

题外话,如何才能产生一个好的设计呢,其实我也不知道。但是最起码的两点:

1.掌握基本的设计方法,平时多思考多总结。
2.分离职责。

我不建议一上来照搬各种设计模式,设计模式只是某个场景下的优美设计方案,并不是放之四海皆准的灵丹妙药。

即使使用了设计模式,你也要看交流电对象,对于熟练掌握设计模式的人来说,模式可以作为通用词汇,用于方便快速准确的交流设计思想,
对于不懂模式的人来说,简直是对牛弹琴,甚至可以能引起对方的反感,

其实这个不成熟的设计方案中,我运用了:职责链模式,模板方法模式,桥接模式,抽象工厂模式,适配器模式。试着找找看…

 

 

 

 

 
 
分类: 领域建模
posted on 2013-01-22 09:33  HackerVirus  阅读(1155)  评论(0编辑  收藏  举报