【5.19】软件构造Lab3

所选定的三个应用:航班管理、高铁车次管理、学习日程管理

三个应用场景的异同:位置的数量分别为1个、2个、多个;除了学习日程管理的位置可更改外,其余两个应用不可更改;资源分别为单个、有序多个、无序多个

3.2 面向可复用性和可维护性的设计:PlanningEntry
3.2.1 PlanningEntry的共性操作
1.位置操作:位置的设定、从固定计划项获取其位置
2.资源操作:资源的分配、从计划项获取资源名称
3.时间属性操作:时间分配、当前时间的获取、从计划项获取时间
【5.19】软件构造Lab3

(以Train Schedule为例)

3.2.2 局部共性特征的设计方案
1.在位置为空时可以进行位置分配
2.在资源为空时可以进行资源分配(如果资源不为空则不可以进行重新设置)
3.时间属性通过Calendar进行当前时间获取
4.状态转换:将状态转换派给state对象进行操作。在state对象中,先判断转换是否合法,然后再进行状态覆盖。
5. Get操作访问CommonPlanningEntry中定义的共性成员变量,包括Location、Resource等。

3.2.3 面向各应用的PlanningEntry子类型设计(个性化特征的设计方案)
(以航班管理为例)
·构造时间、位置、航线名称等时资源不是必须的(可以后期进行分配)
·位置设定与获取:提供两个位置,在未起飞时可以进行分配获取位置时返回装有两个位置的List资源分配;状态为WAITING时可以进行分配,否则不予分配时间获取;返回两个时间的数组比较:若提供的航线的起飞时间早于当前航线的起飞时间则返回1,若晚于则返回-1,否则返回0
·通过getLocationOrigin()、getLocationTerminal()方法获得起飞、降落机场(在Activity Calendar中则用getStrLocation()获得活动地点)
【5.19】软件构造Lab3
【5.19】软件构造Lab3

·重写不同的equals、hashcode、toString方法
【5.19】软件构造Lab3
3.3 面向复用的设计:R
以航班管理为例
【5.19】软件构造Lab33.4 面向复用的设计:Location
由于三个应用位置数量不同,故采用List进行存储。
【5.19】软件构造Lab3
3.5 面向复用的设计:Timeslot
采用List进行存储,构建两个List存储位置到达和离开时间。
【5.19】软件构造Lab3
3.6 面向复用的设计:EntryState及State设计模式
·EntryState是一个可变对象,成员变量有类型为enum的state。
【5.19】软件构造Lab3

·由于状态是可变的,故需要设置一个set方法来满足状态之间的转换
【5.19】软件构造Lab3

·方法setAvailability()用来判断合法性,该方法利用到了EntryStateEnum中的静态Map变量
【5.19】软件构造Lab3

·上一点中提及的静态Map变量基于委派EntryState查询“可以到达的新状态”的一个List,通过匿名对象初始化方法来初始化。再建立一个属于枚举的成员方法,返回“可以到达的新状态”。调用原状态的枚举对象查询该List
【5.19】软件构造Lab3【5.19】软件构造Lab3
3.7 面向应用的设计:Board
(以航班管理为例)
·每个机场有1小时内到达航班和起飞航班的显示。Board是一个抽象类,有3个不同的实现类,分别完成3个应用场景的Board。在初始化时,保存PlanningEntryCollection作为成员变量。
【5.19】软件构造Lab3
·在可视化设计中,输入为当前时间、位置字符串和起飞状态(若位置为空,则认为查询所有机场)

【5.19】软件构造Lab33.8 Board的可视化:外部API的复用
遍历PlanningEntry获得航班时间并与当前时间进行对比,若差距在预设的范围内(HOURS_RANGE=1)则将信息记录到Vector,再将Vector加入二维Vector。Board.makeTable()中新建JTable,将信息输入表格,再将表格加入JFrame进行可视化

【5.19】软件构造Lab3
3.9 可复用API设计及Façade设计模式
3.9.1 检测一组计划项之间是否存在位置独占冲突
·保存每个位置的所有计划项
·遍历所有计划项,考察是否有冲突,并更新

3.9.2 检测一组计划项之间是否存在资源独占冲突
思路与3.9.1相似,不多赘述。

3.9.3 提取面向特定资源的前序计划项
·该步骤是要搜索使用同一资源、计划时间在选定计划项之前且最的计划项。首先进行初始化。
·遍历所有计划项,找出使用相同资源的计划项
·在迭代中比较筛选并更新

3.10 设计模式应用
3.10.1 Factory Method
(以航班管理为例)
【5.19】软件构造Lab3
3.10.2 Iterator
(以航班管理为例)
【5.19】软件构造Lab33.10.3 Strategy
在PlanningEntryAPIs中设置abstract方法,并用子类来实现该方法。

3.11 应用设计与开发
3.11.1 航班应用
·初始化
【5.19】软件构造Lab3可视化
【5.19】软件构造Lab3
·新建计划项

【5.19】软件构造Lab3
·查询
【5.19】软件构造Lab3

·API:冲突检查,查找前置计划项
【5.19】软件构造Lab33.12 基于语法的数据读入
·读入一个数据就进行匹配,根据数据格式进行提取
(略)

3.13 应对面临的新变化
3.13.1 变化1:航空管理
从2站变为3站,改变方法:取3个站位置/资源时用不同的静态常量作为下标。其余获取资源方式相同,通过继承父类,进行方法的增加/重载以达到变化的目的
【5.19】软件构造Lab3【5.19】软件构造Lab3
3.13.2 变化2:高铁管理
分配资源后不能取消,通过重写cancel()方法增加判断语句限制前置状态
【5.19】软件构造Lab3

3.13.3 变化3:学习活动日程管理
学习活动也可以被临时暂停,通过增加可阻塞的活动名单解决
【5.19】软件构造Lab33.14 Git仓库结构
【5.19】软件构造Lab3

实验过程中收获的经验和教训:
(1) 重新思考Lab2中的问题:面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?本实验设计的ADT在五个不同的应用场景下使用,你是否体会到复用的好处?
ADT与针对应用场景的编程的差异:在ADT的复用中,不仅仅是面向场景的编程的函数的复用,ADT能够复用数据结构和一系列方法
复用的好处就是能够通过较少的代码实现多个应用与功能,使代码更加清晰。

(2) 重新思考Lab2中的问题:为ADT撰写复杂的specification, invariants, RI, AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?
意义在于编程的过程中,这些工作能够为编程提供指导,提高编程效率,以后的编程过程中也会尝试将这项工作继续下去。

(3) 在编程中使用设计模式,增加了很多类,但在复用和可维护性方面带来了收益。你如何看待设计模式?
设计模式提高了可复用性,使代码更加有序。

(5) 你之前在使用其他软件时,应该体会过输入各种命令向系统发出指令。本次实验你开发了一个解析器,使用语法和正则表达式去解析输入文件并据此构造对象。你对语法驱动编程有何感受?
正则表达式的学习是困难的,经过学习慢慢感受到使用正则表达式能够用很少的代码完成数据判断等功能,很实用。

(7) “抽象”是计算机科学的核心概念之一,也是ADT和OOP的精髓所在。本实验的五个应用既不能完全抽象为同一个ADT,也不是完全个性化,如何利用“接口、抽象类、类”三层体系以及接口的组合、类的继承、设计模式等技术完成最大程度的抽象和复用,你有什么经验教训?
对于ADT,最重要的属性就是要有自己的不变量,即对于每种运行状态,不变量永远都是正确的。其次, ADT对于整个整个程序设计的过程中有着很重要的作用。