写在前面

上一篇博客我们主要讨论了为什么要关注软件的可复用性和可维护性,给出了从上述两个方面评价你的软件的一些指标,并介绍了我在完成Lab3的框架设计时所应用的主要的设计思想——CRP原则(利用委托机制增强可复用性以及可维护性)。
这一次,我们继续围绕Lab3中涉及的其他一些有关为上述两个性质而应用的设计技术,主要包括以下设计模式:strategy(行为设计模式)、state(行为)以及factory(创建模式)。
最后我还要谈一下正则语言的应用,介绍一下我对将其应用到我的Lab作业中的曲折过程~

关于可复用性和可维护性的设计模式

state
想要先讲这个模式的原因是,在Lab3中所有计划项ADT都是有一定状态的(比如计划项对象处于已取消状态或已挂起状态等等),因此这个模式还是相对宏观的穿插应用于整个lab的完成设计上。随后我们再讲其他用起来相对零散的设计模式。
实验中要求PlanningEntry 及其子类型需要记录计划项实体的当前“状态”,并且需要state设计模式来完成这个设计。state设计模式的定义和应用背景已经有很多大佬讲过了,这里我主要说一下它在实验中的应用。
所有计划项的可能处于的状态无外乎以下几种:未分配资源(WAITING)、已分配资源(ALLOCATED)、已启动(RUNNING)、已完成(ENDED)、已取消(CANCELLED)、挂起中(BLOCKED),某一种计划项所可能含有的所有状态为其子集。为了通过这些状态来规定计划项的行为,我们要在每个状态对应的状态类中都实现计划项中与状态有关的相应方法,比如启动计划项的方法run()、取消cancel()等等,这些方法的主要目的是对一个计划项对象当前所处的状态进行改变,因此我们需要描绘出其所有状态之间允许的转化逻辑。画出其逻辑转化图对设计有较大的帮助,这一点我也是通过这次实验学到的(老师在实验指导书中给出了状态间的逻辑转换图):Software Construction——继续讨论可复用和可维护性软件的设计
通过上面逻辑图,我们在状态类中实现方法时就会更加明确,减少出bug的几率。说到这一点,我们在构造软件时很多情况下都可以通过画图使得我们设计的思想更加具体化,从而减少实现时的困难度,比如我们画类间关系的UML图,画对象的snapshot图(这个就是用于运行分析了)等等。
具体的实现我就直接贴一部分状态类的代码,大家可以注意其中方法的实现,以及单例模式的应用:
Software Construction——继续讨论可复用和可维护性软件的设计
我们可以看待,每个状态类仅有一个该类状态的static实例,并且构造器被隐藏。
另外是部分方法的实现:Software Construction——继续讨论可复用和可维护性软件的设计
在处于RUNNING状态时,我们可以end却不可以cancel,因此我们在前者的实现中设定新的状态,后者则报错提醒client。

factory:这种设计模式用于创建对象,目的是不让client知道创建对象所属的具体类,或者让client知道所有要用到的对象的类太麻烦、没必要,我们就为这些对象提供工厂方法用于创建。
这里我借用课件中用到的UML图来说明其思想:
Software Construction——继续讨论可复用和可维护性软件的设计
我们首先需要提供一个Creator接口,里面放一个创建创建对象的方法等待具体类实现。创建不同对象的工厂方法类就是该接口的具体实现,也就是下面的ConcreateCreatorOne等,它们负责创建右边所指向的对象类的对象。以我们这次实验为例,下图是我为课程计划项实现的工厂方法类,工厂方法中定义了四个我上一次提到的用于委托的对象:
Software Construction——继续讨论可复用和可维护性软件的设计
随后在客户端直接调用即可。
Software Construction——继续讨论可复用和可维护性软件的设计

strategy:对于ADT内部的一种方法实现,我们希望可以在每一次调用它时根据自己的意愿选择不同的算法,别如对一组数进行排序,我们自然希望在数量小时选择插入排序等常数因子小的方法,而在规模大时选择快排等增长率小的排序方式。
这就用到了strategy模式,可以利用委托,在client调用方法时将相应算法策略作为参数传入方法,并在方法中委托给该策略对象去动态的实现。而策略对象源于算法接口的具体实现类,我们为某个方法设定相应的strategy接口,并在其不同的具体实现类中给出不同的算法实现。以这次试验的查询位置冲突方法为例,我们要实现如下client需要调用的方法:
Software Construction——继续讨论可复用和可维护性软件的设计
具体的实现被委托给了传入的参数thisCheckStrategy,它属于下面的接口:
Software Construction——继续讨论可复用和可维护性软件的设计
我们为该接口提供了两个实现类,每个类中有不同的算法实现(具体怎么实现的就不献丑了~):
暴力算法:
Software Construction——继续讨论可复用和可维护性软件的设计
以及一种优化算法:
Software Construction——继续讨论可复用和可维护性软件的设计
client通过选择其中一类创建对象作为参数传入方法,即可选择方法的不同实现。

关于正则语言:

我们知道匹配大量的有一定格式的文本需要用到正则表达式,在java中具体通过Pattern和Match两个类来实现,具体的:
Software Construction——继续讨论可复用和可维护性软件的设计
主要分为如下几个步骤,第一行设定正则表达式的格式(具体符号的意义可以查询菜鸟教程,说得很全),第二行方法Pattern.compile和第四行方法obj.matcher搭配,对读入的行进行匹配。以及obj.matches判断是否匹配成功,最后还可以通过group方法获得第i个括号中的串。
看起来没啥毛病,实际上,我一开始是这样一行一行的读,一行一行的根据原来文本的格式进行判断的,结果就是,原来的文本格式有十三行:Software Construction——继续讨论可复用和可维护性软件的设计
然后我就憨憨的写了十三个pattern…
最后写出了两百行代码。

傻成这样的我到现在居然还没被退学真是个奇迹。
实际上,我们可以用StringBuilder把所有行都读到一个串里:Software Construction——继续讨论可复用和可维护性软件的设计
随后,将所有的格式写到一个正则表达式中(\n衔接即可),随后应用Match类的find方法搭配一个while循环进行匹配!这个方法能省去上面多费的很多精力。
这回就说这么多吧…大家懂得就当看个笑话,之前不知道的希望引以为戒…

相关文章: