1 实验目标概述
本次实验覆盖课程第 3、4、5 章的内容,目标是编写具有可复用性和可维护
性的软件,主要使用以下软件构造技术:
⚫ 子类型、泛型、多态、重写、重载
⚫ 继承、代理、组合
⚫ 常见的 OO 设计模式
⚫ 语法驱动的编程、正则表达式
⚫ 基于状态的编程
⚫ API 设计、API 复用
本次实验给定了五个具体应用(高铁车次管理、航班管理、操作系统进程管
理、大学课表管理、学习活动日程管理),学生不是直接针对五个应用分别编程实现,而是通过 ADT 和泛型等抽象技术,开发一套可复用的 ADT 及其实现,充分考虑这些应用之间的相似性和差异性,使 ADT 有更大程度的复用(可复用性)和更容易面向各种变化(可维护性)。
2 实验环境配置
这次实验需要的环境前两个实验已经配置完成。
在这里给出你的GitHub Lab3仓库的URL地址(Lab3-学号)。
https://github.com/ComputerScienceHIT/Lab3-1180800811.git
3 实验过程
请仔细对照实验手册,针对每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
1.1 待开发的三个应用场景
列出你所选定的三个应用。
分析三个应用场景的异同,理解需求:它们在哪些方面有共性、哪些方面有差异。
选用的三个应用:
1、航班管理 2、高铁车次管理 3、大学课表管理
1.
三个应用的共性:
①均表示一个待执行的活动/任务,它需要配置特定类型/数的资源,并在特定的物理位置加以执行。
②活动的状态有交集:都有未分配资源、已
分配资源但未启动、已启动、已完成、已取消五个状态。
三个应用的差异:
①位置差异:航班:两个位置,位置可共享
高铁车次:多个位置,位置可共享 大学课程:一个位置,位置不可共享
②资源差异:
航班/课程:单个可区分的资源(飞机) 高铁:多个可区分的资源
1.
③状态差异:
高铁相较于航班/课程,多一个可阻塞的状态
1.
④位置是否可更改差异:
航班/高铁:可提前设定,设定后不可更改 课程:可提前设定,设定后可更改
1.
⑤时间差异:
高铁:多个起止时间对 课程/航班:1个时间起止对
1.
3.2 面向可复用性和可维护性的设计:PlanningEntry
该节是本实验的核心部分。
3.2.1 PlanningEntry的共性操作
① 和状态有关的方法
⚫ 启动一个计划项 ⚫ 结束一个计划项 ⚫ 取消一个计划项 ⚫ 获取当前的状态 ⚫ 判断当前状态是否可接受 ⚫ 设定计划项的状态
1.
② getter方法
⚫ 获取计划项使用的全部资源 ⚫ 获取计划项的起止时间 ⚫ 获取计划项的名字 ⚫ 得到计划项所用的位置和时间对的对应关系(主要用于API设计,判断位置冲突)
1.
③ setter方法
⚫ 设定计划项的名字
1.
说明:
①在PlanningEntry中提供一个统一的获取资源的方法getresource,这个方法可以用来APIs中判断资源冲突,返回值类型是一个List,因为考虑到可能使用多个资源,也可能使用单个资源,所以一起放在一个List列表存储所有的资源,
②得到计划项所用的位置和时间对的对应关系是为了3.10 API的设计需要判断位置冲突。通过判断相同位置对应的时间是否重叠来判断是否有位置冲突。这个方法既可以得到所有的时间对,也可以得到所有的位置。
以上两个方法抽象出来放在公共接口PlanningEntry中,完全是为了设计API。经验证,这样设计之后,314change我不需要改动任何的APIs类的代码。可复用性很高。
3.2.1 局部共性特征的设计方案
创建一个新的子类型:利用工厂方法能够创建一个指定类型的子类
#3.2.3 面向各应用的PlanningEntry子类型设计(个性化特征的设计方案)
1.设计方案:方案5:CRP,通过接口组合
思想:
① 把三个应用公有的特征抽象成一个公共的接口PlanningEntry ② 对于三个应用的不同维度的差异,为每个维度上的不同特征取值分别定义不同的 接口,在接口中定义特殊的操作,分别实现针对该维度接口的不同实现类, 实现其特殊操作逻辑。 ③ 对于具体的应用,通过接口组合,将各种局部共性行为复合在一起形成满足每 个应用要求的特殊接口(包含了该应用内的全部特殊功能),从而该应用子类可直 接实现该组合接口。 ④ 在应用子类内,不是直接实现每个特殊操作,而是通过 delegation 到外部每 个维度上的各具体实现类的相应特殊操作逻辑
1.
以TrainEntry为例:通过接口的组合来形成满足应用的接口。
2.个性化特征方案
三个子类的差异方法就是Location、Timeslot 、Resource 属性的获取和修改。以及状态的转化。
TrainEntry:
构造器方法: 无参数、带参数
方法
CourseEntry:构造器方法
![在这里插入图片描述]
其他方法:
FlightEntry 构造器方法
其他方法
测试:
3.3 面向复用的设计:R
1.Plane
属性:
private String PlaneNumber ;//飞机编号 private String MachineNumber ;//机型号 private int Size ;//座位数 private double Age ;//机龄
1.
checkRep:
方法:
2.Railway
属性:
private String Number ;//编号
private Type type ; //车厢类型 private int Size ; //定员数 private int Year ;//出厂年份
1.
checkRep:
方法:
3.Teahcer
属性:
private String IdNumber ;//教师的身份证号 private String Name ;//教师的名字 private boolean Sex ; //教师的性别,true表示男,false表示女 private String Title ;//教师职称
1.
checkRep:
方法
测试
3.4 面向复用的设计:Location
属性:
private double longitude ; //经度 private double latitude ;//纬度 private String name ; //位置名称 private boolean share ;//位置是否可以共用,true表示可以共用,false 表示不能共用
1.
checkRep:
**Equals方法:**由于考虑到老师给的航班管理的文件对位置的读取没有经纬度的信息,而且老师说经纬度是为了以后复用可能被用来求解距离,所以我觉得在本次实验中,可以认为经纬度没有什么作用,只要位置的名字相等,就可以认为两个位置相同。
其他方法
测试:
3.5 面向复用的设计:Timeslot
1.属性:
private Calendar date1 = Calendar.getInstance();//起始时间 private Calendar date2 = Calendar.getInstance();//终止时间
1.
2.checkRep
3.方法
测试
3.6面向复用的设计:EntryState及State设计模式
1.State接口
State接口时状态类的公共接口,只有两个方法,改变状态和判断是否是可接受转态
2.具体的状态类
WAITTING.java//未分配资源、 ALOCATED.java//已分配资源但未启动 RUNNING.java//已启动 CANCELLED.java//已取消 ENDED.java//已完成 BLOCKED.java//挂起
1.
由状态关系转移图可知,对于每个状态类来说,只能转换为特定的状态类。
① 以WAITTING状态为例,只能转换为ALOCATED和CANCALLED两个状态,并且状态不可接受
②ALOCATED状态
③RUNNING状态
④BLOCKED状态
⑤CANCELLED状态
⑥ENDED状态
测试:
3.7 面向应用的设计:Board
思路:
对于每一个信息板,都有一个当前时间,当前位置与他相对应,并且包含了一组计划项。因此属性就是当前时间、当前位置、一组计划项
功能:
①对于每个信息板,首先实现按照实验指导书所说显示出发生在计划板所在位置和当前时间相差一个小时内的计划项信息,②其次展示所有的发生在该计划板的计划项信息(没有相差一个小时的限制)。
实现方法:
首先在所有的计划项中找出和信息板位置相关的计划项,将他们按照发生在当前位置的时间排好序。然后利用jtable组件可视化信息板即可。
注意:
而且当前时间并不是系统显示的时间,每次当前时间都是需要由用户输入的。
1.CourseCalendarBoard
属性:
private Location location ;//信息板所在的的位置
private List course = new ArrayList() ;//一系列的计划项
private Calendar time = Calendar.getInstance() ; //当前时间
方法:
注释:
visualize方法显示的是按照实验指导书所说显示出发生在计划板所在位置和 当前时间同一天的课程信息。 show方法显示的是发生在当前位置的所有计划项的信息,没有时间要求。 changestate方法:由于每次显示信息板都要输入当前时间,那么每次 输入当前时间的不同,相交于用户输入的当前时间而言,所有的课程的状 态也是不同的,因此changestate方法就是根据用户输入的当前时间来改变 计划项的状态。
1.
**getCourse()方法:**得到的是所有发生在该位置的课程
**isSameDay()方法:**判断两个时间是否是同一天
2.FlightScheduleBoard
属性:
private Calendar time = Calendar.getInstance() ;//屏幕版当前时间
private Location location ; //屏幕板所在的位置
private List flight = new ArrayList() ;//一系列的计划项
方法:
注释:
visualize方法显示的是按照实验指导书所说显示出发生在计划板所在位置和当 前时间相差一个小时的航班信息。 show方法显示的是发生在当前位置的所有计划项的信息,没有时间要求。
1.
Show方法示例
Visualize方法示例
- TrainScheduleBoard
属性:
private Calendar time = Calendar.getInstance() ;//屏幕版当前时间
private Location location ; //屏幕板所在的位置
private List train = new ArrayList() ;//一系列的计划项
方法:
注释:
visualize方法显示的是按照实验指导书所说显示出发生在计划板所在位置和当前时间相差一个小时的高铁车次信息。
show方法显示的是发生在当前位置的所有计划项的信息,没有时间要求。
设计思路:对于每一个经停location的高铁车次(由getTrain方法得到),都对应一个抵达时间/出发时间,所以我是实现了gettrain1方法,得到所有抵达location的高铁车次和对应的抵达时间,这种对应关系用Treemap<Calendar,TrainEntry>存储,然后对键按照时间进行排序。然后visualize方法就可以按照时间增序显示所有的高铁车次信息。同理对于出发车次也是如此。
changestate方法:由于每次显示信息板都要输入当前时间,那么每次输入当前时间的不同,相交于用户输入的当前时间而言,所有的高铁车次的状态也是不同的,因此changestate方法就是根据用户输入的当前时间来改变计划项的状态。
gettrain1方法
测试
3.8 Board的可视化:外部API的复用
只要把所有显示的东西放进一个二维数组,再利用jtable组件就能显示出当前的信息板。
Visualize方法思路:首先用getcourse得到所有按时间排好序的和该位置相关的课程信息,然后遍历,如果课程和当前时间是同一天,就把相应的信息放进二维数组内。最后借助于外部API就可以显示出来。
说明:Show类的show方法,参数是一个二维数组rowData,和一维数组(第一行信息)和一个JFrame容器。该方法用来可视化。
Show方法:和visualize方法类似,只是少了判断和当前时间是否是同一天的约束。
3.9 可复用API设计及Façade设计模式
Façade设计模式
客户端需要通过一个简化的接口来访问复杂系统内的功能,我们只需要提供一个统一的接口来取代一系列小接口调用,相当于对复杂系统做了一个封装,简化客户端使用。
在lab3可复用API设计中,我们需要把检查资源冲突、检查位置冲突、获取前序计划项的方法封装在一个APIs类中,通过提供这个统一的类来提供功能,简化客户端的使用。
3.9.1检测一组计划项之间是否存在位置独占冲突
位置冲突:即不同的计划项在同一个时间点上占用了相同的不可共享位置(在这个意义上,这个方法不适用与高铁车次应用和航班应用)。
设计思路:对于使用不可共享的位置计划项而言,遍历每个计划项,如果任意两个计划项的运行时间存在重叠,则比较他们的位置,如果位置相等,则说明存在位置冲突。否则不存在位置冲突。
3.9.2 检测一组计划项之间是否存在资源独占冲突
资源冲突:即不同的计划项在同一个时间点上占用了相同的资源
设计思路1:对于使用不可共享的位置计划项而言,遍历每个计划项,如果任意两个计划项的运行时间存在重叠,则比较他们的位置,如果位置相等,则说明存在位置冲突。否则不存在位置冲突。
设计思路2:对于使用不可共享的位置计划项而言,遍历每个计划项,如果任意两个计划项存在使用相同的资源,则比较他们的运行时间,如果运行时间重叠,则说明存在位置冲突。否则不存在位置冲突。
采用策略模式,由用户来选择调用的方法.其中公共接口是CheckResourceExclusiveConflict.java,两种不同的实现分别是checkResourceExclusiveConflict1.java
和 checkResourceExclusiveConflict2.java。根据传入的参数来选择调用哪个方法来实现。
3.10节模式的引用中,策略模式会重新提及这个方法。
3.9.3提取面向特定资源的前序计划项
特定资源的前序计划项:即在一组计划项中,针对某个资源 r 和使用 r 的某个计划项 e,从一组计划项中找出 e 的前序 f,f 也使用资源 r,f 的执行时间在 e 之前,且在 e 和 f 之间不存在使用资源 r 的其他计划项。
设计思路:首先初始化一个前序计划项x和对应的最晚结束时间latestTime,遍历所有的计划项,如果某个计划项和计划项e共用资源r,而且该计划项的结束时间晚于latestTime,则重新设定前序计划项e和最晚结束时间latestTime。循环结束,返回x即可。
测试
3.10 设计模式应用
请分小节介绍每种设计模式在你的ADT和应用设计中的具体应用。
3.10.1 Factory Method
思路:设计一个工厂类统一的接口factoryInterface,工厂类Factory继承这个接口并实现里面的工厂方法。工厂类的工厂方法可以根据指定的类型来创建相应的计划项。
在PlanningEntry类,就可以调用工厂方法来创建一个新的计划项。
3.10.2 Iterator
我的思路:让board类实现Iterable接口,并且实现Iterator方法即可。对于每一个信息板而言,都对应一个当前位置,信息板的迭代器只需要遍历和这个位置相关的计划项既可。首先,先得到所有和当前位置相关的计划项,然后按照时间进行排序。最后实现一个自己的迭代器,board类的迭代器返回自己实现的迭代器既可。
1.CourseCalendarBoard的迭代器方法
自己实现的迭代器:
属性:
private List course1 = getCourse() ;//获取和当前计划板所 在的位置相关的计划项
private int curror = -1;//
private int size = course1.size() ;//计划项的数量
方法:
hasNext :判断是否还有下个元素
next:下一个元素
remove方法:本次实验用不上这个方法,所以不需要实现这个方法
实现Comparator方法:
因此,在CourseCalendarBoard类中,只要返回我们实现的迭代器即可。
- FlightScheduleBoard的迭代器方法
自己实现的迭代器:
属性:
private List flight1 = getFlight2() ;//抵达位置是location的所有航班
private List flight2 = getFlight1() ;//出发位置是location的所有航班
private int curror = -1;
private int size1 = flight1.size() ; //抵达位置是location的航班个数
private int size2 = flight2.size();//出发位置是location的航班的个数
属性说明:由于机场对应抵达航班和出发航班,所以迭代器要遍历所有的抵达航班和出发航班。
方法:hasNext , next方法同上
实现Comparator方法:
最后FlightScheduleBoard类中,只要返回我们实现的迭代器即可。
3.TrainScheduleBoard方法
属性:
private List t = getTrain() ;//所以经停location的高铁车次
private int curror = -1;
private int size = t.size() ;//高铁车次个数
属性说明: 所有经停location的高铁车次已经按照时间排好序
实现Comparator方法:
最后TrainScheduleBoard类中,只要返回我们实现的迭代器即可。
3.10.3 Strategy
策略模式:同一个功能用不同的方法去实现,具体客户端选择哪种实现由用户决定。
思路:我把策略模式用在了3.9节中判断资源冲突的方法中。首先创建一个公共接口CheckResourceExclusiveConflict.java,两种不同的实现分别是checkResourceExclusiveConflict1.java
和 checkResourceExclusiveConflict2.java。根据传入的参数来选择调用哪个方法来实现。
3.11 应用设计与开发
3.11.1 航班应用
1.FlightSchedule 类
设计思路:所有的方法均是针对APP来设计,方法的参数也是根据实际需求来设计。创建一个航班管理,可以读取文件创建,也可以自己手动输入信息进行创建。
航班管理:航班管理应用由一系列的航班组成,其中包含了一系列的可用飞机和可用机场,并且对应一个当前时间。
属性:
private List resource = new ArrayList() ;//可用的资源
private List location = new ArrayList() ;//可用的位置
private List flightEntry = new ArrayList() ;//一系列计划项
private Calendar time = Calendar.getInstance();//当前的时间
主要实现的功能:
⚫用户提供必要信息,管理(查看、增加、删除)可用的资源; ⚫ 用户提供必要信息,管理(查看、增加、删除)可用的位置; ⚫ 用户提供必要信息,增加一条新的计划项; ⚫ 用户提供必要信息,取消某个计划项; ⚫ 用户提供必要信息,为某个计划项分配资源; ⚫ 用户从文件读取数据创建一个航班应用 ⚫ 用户提供必要信息,启动某个计划项; ⚫ 用户提供必要信息,以重启动某个已挂起的计划项; ⚫ 用户提供必要信息,结束某个计划项; ⚫ 用户选定一个计划项,查看它的当前状态; ⚫ 检测当前的计划项集合中可能存在的位置和资源独占冲突 ⚫ 针对用户选定的某个资源,列出使用该资源的所有计划项(包含尚 未开的,始执行的、执行中的、已经结束的)。用户选中其中某个计划 项之后,可以找出它的前序计划项 ⚫ 选定特定位置,可视化展示当前时刻该位置的信息板 ⚫ 展示和某个位置相关的所有计划项信息
1.
方法:
2.TrainScheduleAPP
用GUI图形界面结合展示
我的思路:
1.用户可以选择从文件中创建计划项集合,也可以手动输入创建计划项集合。
2.增加一个计划项的时候,只需要分配位置和时间即可,不需要分配资源。而且分配了的位置会自动添加为可用位置。
3.展示资源冲突和位置冲突的时候,提示信息显示在终端,并没有用GUI组件来提示信息,GUI只是提示了有无冲突。
4.对于和状态有关的功能,一般我都指明需要用户输入一个当前时间。这样能够更灵活的展示状态变化。
执行流程:
1.增加可用的资源
2.增加一个新的计划项(可以通过读取文件创建一系列计划项)
(也可以先2后1,但必须保证计划项分配资源之前得增加可用资源)
3.给新的计划项分配资源
其他的功能可以随便选择顺序。
1.读取文件创建
3.11.2高铁应用
1.TrainSchedule 类
设计思路:所有的方法均是针对APP来设计,方法的参数也是根据实际需求来设计。和其他的两个类的功能及方法特别类似。
高铁管理:高铁管理应用由一系列的高铁车次组成,其中包含了一系列的可用车厢和可用站,并且对应一个当前时间。
属性:
private List resource = new ArrayList() ;//可用的资源
private List location = new ArrayList() ;//可用的位置
private List courseEntry
= new ArrayList() ;//一系列计划项
private Calendar time = Calendar.getInstance() ;//当前时间
主要实现的功能:
⚫用户提供必要信息,管理(查看、增加、删除)可用的资源; ⚫ 用户提供必要信息,管理(查看、增加、删除)可用的位置; ⚫ 用户提供必要信息,增加一条新的计划项; ⚫ 用户提供必要信息,取消某个计划项; ⚫ 用户提供必要信息,为某个计划项分配资源; ⚫ 用户提供必要信息,阻塞某个计划项; ⚫ 用户提供必要信息,启动某个计划项; ⚫ 用户提供必要信息,以重启动某个已挂起的计划项; ⚫ 用户提供必要信息,结束某个计划项; ⚫ 用户选定一个计划项,查看它的当前状态; ⚫ 检测当前的计划项集合中可能存在的位置和资源独占冲突 ⚫ 针对用户选定的某个资源,列出使用该资源的所有计划项(包含 尚未开的,始执行的、执行中的、已经结束的)。用户选中其中某个 计划项之后,可以找出它的前序计划项 ⚫ 选定特定位置,可视化展示当前时刻该位置的信息板 ⚫ 展示和某个位置相关的所有计划项信息
1.
方法:
2.TrainScheduleAPP
用GUI图形界面结合展示
我的思路:
1.增加一个计划项的时候,需要分配若干个时间对和位置对,我的设计是每次只能增加一对时间和一对位置。如果有多个位置和时间,需要添加多次。
2.分配资源也是一样,每次只能分配一个车厢,如果需要分配多个车厢,则需要分配多次。
3.展示资源冲突和位置冲突的时候,提示信息显示在终端,并没有用GUI提示信息,GUI只是提示了有无冲突。
4.对于和状态有关的功能,一般我都指明需要用户输入一个当前时间。这样能更灵活的展示状态变化。
提示:由于对GUI设计不是很熟练,界面做的比较难看。每次查看信息后如果点击关闭表格窗口,会导致GUI退出。所以建议老师每次如果输入命令的时候不要把表格的窗口关闭。
执行流程:
1.增加可用的资源
2.增加一个新的计划项
(也可以先2后1,但必须保证计划项分配资源之前得增加可用资源)
3.给新的计划项分配资源
其他的功能可以随便选择顺序。
增加一个新的计划项
增加一个新的计划项的时候,需要分配若干个时间对和位置对,我的设计是每次只能增加一对时间和一对位置。如果有多个位置和时间,需要添加多次。
必须保证第一次输入的终止位置和第二次输入的起始位置是一样的
给计划项分配资源
分配资源也是一样,每次只能分配一个车厢,如果需要分配多个车厢,则需要分配多次。每次分配资源的时候都会展示出当前的可用资源
3.11.3 课程应用
1.CourseCalendar 类
设计思路: CourseCalendar类中所有的方法均是针对APP来设计的,参数是根据实际需要来设定的。比如增加一个计划项:需要提供计划项基本的信息:计划项的名字,计划项的位置,计划项的起止时间。启动一个计划项:也需要计划项的基本信息: 计划项的名字,计划项的位置,计划项的起止时间。具体的方法实现就是基本的调用前面的已经实现的方法。(详细见代码)
课表管理:课表应用由一系列的课程组成,其中包含了一系列的可用教师和可用教室,并且对应一个当前时间。
属性:
private List resource = new ArrayList() ;//可用的资源
private List location = new ArrayList() ;//可用的位置
private List courseEntry = new ArrayList() ;//一系列计划项
private Calendar time = Calendar.getInstance() ;//当前时间
主要实现的的功能:
⚫用户提供必要信息,管理(查看、增加、删除)可用的资源; ⚫ 用户提供必要信息,管理(查看、增加、删除)可用的位置; ⚫ 用户提供必要信息,增加一条新的计划项; ⚫ 用户提供必要信息,取消某个计划项; ⚫ 用户提供必要信息,为某个计划项分配资源; ⚫ 用户提供必要信息,启动某个计划项; ⚫ 用户提供必要信息,以变更某个已存在的计划项的位置; ⚫ 用户提供必要信息,以重启动某个已挂起的计划项; ⚫ 用户提供必要信息,结束某个计划项; ⚫ 用户选定一个计划项,查看它的当前状态; ⚫ 检测当前的计划项集合中可能存在的位置和资源独占冲突 ⚫ 针对用户选定的某个资源,列出使用该资源的所有计划项(包含尚 未开的,始执行的、执行中的、已经结束的)。用户选中其中某个计划 项之后,可以找出它的前序计划项 ⚫ 选定特定位置,可视化展示当前时刻该位置的信息板 ⚫ 展示和某个位置相关的所有计划项信息
1.
2.CourseCalendarAPP
用GUI图形界面展示出来
我的思路:
1.增加一个计划项的时候,只需要分配位置和时间即可,不需要分配资源。而且分配了的位置会自动添加为可用位置。
2.展示资源冲突和位置冲突的时候,提示信息显示在终端,并没有用GUI提示信息,GUI只是提示了有无冲突。
3.对于和状态有关的功能,一般我都指明需要用户输入一个当前时间。这样能够更灵活的展示状态变化。
运行流程:
1.先增加可用的资源
2.增加一个新的计划项
(也可以先2后1,但必须保证计划项分配资源之前得增加可用资源)
3.给新的计划项分配资源
其他的功能可以随便选择顺序。
提示:由于对GUI设计不是很熟练,界面做的比较难看。每次查看信息后如果点击关闭表格窗口,会导致GUI退出。所以建议老师每次如果输入命令的时候不要把表格的窗口关闭。
3.12 基于语法的数据读入
从文件中读取数据创建航班计划项分为两个过程,由于航班数据每13行代表一个计划项,因此每次读取13行就创建一个计划项。所以第一个过程是将13行数据读取到一个字符串中,第二个过程将这个字符串进行解析,提取创建航班所需要的数据创建一个新的航班。
提示:一旦我设计的正则表达式和文件中的数据匹配不到,立即抛出异常,提示错误信息。(经运行,文件1存在和实验指导书指明的语法错误)
1.从文件中提取13行数据到一个字符串s中,然后调用getFileFlightEntry函数创建一个新的计划项。(跳过空行)
2.利用字符串来提取构建航班需要的信息,匹配的正则表达式为:
Pattern pattern1 =Pattern.compile(“Flight:([\d]{4}-[\d]{2}-[\d]{2}),([A-Z]{2}[\d]{2,4})\n{\nDepartureAirport:(.?)\nArrivalAir port:(.?)\nDepatureTime:([0-9]{4}-[0-9]{2}-[0-9]{2}\s[0-9]{2}:[0-9]{2})\nArrivalTime:([0-9]{4}-[0-9]{2}-[0-9]{2}\s[0-9]{2}:[0-9]{2})\nPlane:([B || N][0-9]{4})\n{\nType:([0-9a-zA-Z]{4})\nSeats:([1-9][\d]{1,2})\nAge:(.*?)\n}\n}\n”);
注意:判断座位数是否符合要求:
注意:判断机龄是否符合要求:
利用正则表达式去和提取出来的字符串进行匹配,若匹配失败,直接抛出异常并提示信息
否则,则提取字符串中的信息来创建新的计划项。
一直循环这两个步骤就可以将文件中的所有信息提取出来
判断航班的时间是否符合指导书要求
3.13 应对面临的新变化
只考虑你选定的三个应用的变化即可。
3.13.1 变化1
变化1:单一位置变成多个位置 ,因此接口组合中的单个位置的接口变为多个位置的接口
变化2:不可阻塞变为可阻塞,因此接口组合中的不可阻塞的接口变为可阻塞的接口。
改变:首先根据两个变化改变一下接口组合。
其次,重写一下新增的接口的方法。然后重写一下相关的类的测试方法。
航班change最主要需要改的地方是board,因为时间和位置都变成了多个,所以对位置的和时间的一一对应的信息的获取工作量更大。
主要change:
1.重写获取和某个位置相关的出发航班和抵达航班的方法
2.稍微改动visualize方法和show方法
3.对于改变状态的方法需要增加blocked状态的改变。(详细见代码)
另外一个change是:
1.控制一个航班的最大的位置数目:因为最多只有一个经停站,所以对于一个航班来说,分配的位置最多数目是3.
2.和TrainEntryApp一样,如果航班有经停站的话,需要一次一次输入,即每次输入只能输入两个位置和两个时间。
输入异常的条件有:时间格式错误,第一个时间第二个时间大,第一次输入的终止位置和第二次输入的起始位置不相同,为同一个航班输入的位置超过3(经停站超过1)
3.航班增加了阻塞的功能。
修改时间:3个小时
3.13.2 变化2
变化之前,高铁车次分配了资源仍可以取消,可以直接调用状态类的方法实现。
变化之后,高铁车次分配了资源不可以取消,则不能直接调用状态类的方法,为了保证代价更小,无需重新为ALOCATED状态类重新设计changestate方法,只需要trainEntry类只要重写取消计划项的方法就行。
修改耗费的时间:10分钟
3.13.3 变化3
变化1:由于我采用的是方案5,接口组合,所以courseEntry的接口组合中单一资源的接口得改变为多资源的接口,同时,我默认为区分老师的优先级是从给某门课程分配教师的顺序来区分。
同时得重写多资源接口中的方法、以及测试类、所有用到courseEntry中和资源操作有关的代码。
重写CourseEntryTest方法
APP不需要修改代码,只是给某门课程分配教师的功能改变了,原来只能分配一个教师,现在可以分配多个教师。
3.14 Git仓库结构
请在完成全部实验要求之后,利用Git log指令或Git图形化客户端或GitHub上项目仓库的Insight页面,给出你的仓库到目前为止的Object Graph,尤其是区分清楚314change分支和master分支所指向的位置。