HIT2020春季学期软件构造Lab3

1 实验目标概述

本次实验覆盖课程第 3、4、5 章的内容,目标是编写具有可复用性和可维护性的软件,主要使用以下软件构造技术:
子类型、泛型、多态、重写、重载
继承、代理、组合
常见的 OO 设计模式
语法驱动的编程、正则表达式
基于状态的编程
API 设计、API 复用
本次实验给定了五个具体应用(高铁车次管理、航班管理、操作系统进程管理、大学课表管理、学习活动日程管理),学生不是直接针对五个应用分别编程实现,而是通过 ADT 和泛型等抽象技术,开发一套可复用的 ADT 及其实现,充分考虑这些应用之间的相似性和差异性,使 ADT 有更大程度的复用(可复用性)和更容易面向各种变化(可维护性)。

2 实验环境配置

实验环境设置请参见 Lab-0 实验指南。
除此之外,本次实验需要你在 Eclipse IDE 中安装配置 EclEmma(一个用于
统计 JUnit 测试用例的代码覆盖度的 plugin)。请访问 http://www.eclemma.org,了解 EclEmma 并学习其安装、配置和使用。
本次实验在 GitHub Classroom 中的 URL 地址为:
https://classroom.github.com/a/z9utaaos

3 实验过程

3.1 待开发的三个应用场景

列出你所选定的三个应用:
1、航班管理
2、高铁车次管理
3、学习日程管理

分析三个应用场景的异同,理解需求:
共同点:
三个应用场景的地点与时间都需要提前确定;
三个应用场景在未开始前均可以取消;
三个应用场景在进行中均不可取消;
不同点:
高铁在中间站停车的时候可以取消;
航班与高铁一旦确定就无法更改起始地与目的地,并且确定后高铁还无法更改中间站,但是学习日程确定之后还能够更改地址;
三个应用场景需要不同类型的资源;

3.2 面向可复用性和可维护性的设计:PlanningEntry

3.2.1 PlanningEntry的共性操作

由下图表得:
在这里插入图片描述
public boolean planningRunning();启动计划项

public boolean planningCancelled();取消计划项

public boolean planningEnded();完成计划项

public String getPlanningName();得到计划项的“名字”

public String getState();得到计划项当前的状态

3.2.2 局部共性特征的设计方案

在这里插入图片描述
两个变量:
plannningName用于存储计划项的“名字”
state是用于保存计划项当前状态的对象引用

方法:
1.public boolean planningRunning():只有在ALLOCATED和BLOCKED状态下,计划项才能启动计划项,并且将计划项的状态state指向Running这个对象;
2. public boolean planningCancelled():只有在WAITING、ALLOCATED和BLOCKED状态下才能取消计划项,并且将计划项的状态state指向Cancelled这个对象;
3. public boolean planningEnded():只有在RUNNING状态下才能取消计划项,并且将计划项的状态state指向Cancelled这个对象;
4. 两个getter:
在这里插入图片描述

3.2.3 面向各应用的PlanningEntry子类型设计(个性化特征的设计方案)

1.飞机航班:

在这里插入图片描述
构造函数:为航班设定计划项名字,时间以及地点,并且将state指向Waiting这个对象;
在这里插入图片描述
public boolean planningAllocated(Aircraft ac):只有在WAITING状态下,才能为航班分配飞机,并且将state指向Allocated这个对象;
在这里插入图片描述
FlightEntry类中的内部方法,用于设定飞机航班的地点、时间和资源信息;
在这里插入图片描述
3个getter:使用String的形式,得到航班的名字、地点、时间和飞机资源的信息;
在这里插入图片描述
public String toString():以String的形式,输出航班的所有信息;
在这里插入图片描述
航班特定方法的接口:
在这里插入图片描述

2.高铁车次:

在这里插入图片描述
构造函数:为高铁设定计划项名字,时间以及地点,并且将state指向Waiting这个对象;
在这里插入图片描述
public boolean planningAllocated(Trains trains):只有在WAITING状态下,才能为高铁分配列车资源,并且将state指向Allocated这个对象;
在这里插入图片描述
public boolean planningBlocked():只有在WAITING状态下,才能阻塞高铁,并且将state指向Blocked这个对象;
在这里插入图片描述
TrainEntry类中的内部方法,用于设定高铁的地点、时间和资源信息;
在这里插入图片描述
3个getter:使用String的形式,得到高铁的名字、地点、时间和资源的信息;
在这里插入图片描述
public String toString():以String的形式,输出高铁的所有信息;
在这里插入图片描述
高铁特定方法的接口:
在这里插入图片描述

3.学习活动:

在这里插入图片描述
构造函数:为学习活动设定计划项名字,时间以及地点,并且将state指向Waiting这个对象;
在这里插入图片描述
public boolean planningAllocated(LearningMaterials l):只有在WAITING状态下,才能为学习活动分配学习资料资源,并且将state指向Allocated这个对象;
在这里插入图片描述
public boolean changeLocation(Location loc):只有在WAITING和ALLOCATED状态下,才能为学习活动更换活动地点;
在这里插入图片描述
ActivityEntry类中的内部方法,用于设定高铁的地点、时间和资源信息;
在这里插入图片描述
3个getter:使用String的形式,得到学习活动的名字、地点、时间和资源的信息;
在这里插入图片描述
public String toString():以String的形式,输出学习活动的所有信息;
在这里插入图片描述
学习活动特定方法的接口:
在这里插入图片描述

3.3 面向复用的设计:R

在这里插入图片描述

1.飞机Aircraft:

变量:用于存储变量的信息;
在这里插入图片描述
构造函数:设定飞机的信息;
在这里插入图片描述
4个getter和toString方法:用于得到飞机的信息;
在这里插入图片描述

2.列车Trains和车厢Train:

车厢Train:
在这里插入图片描述
构造函数:用于设定车厢的信息;
在这里插入图片描述
4个getter和toString方法:用于得到车厢的信息;
在这里插入图片描述
列车Trains:由一组车厢组成;
在这里插入图片描述
public void addATrain(int number, int type, int seating, int yearOfManufacture):往列车中添加一个车厢;
在这里插入图片描述
2个不同的构造函数:用于不同情况下生成一个列车实例;
方法一:生成一个仅有列车编号trainsNumber的列车实例,然后通过addATrain方法一节一节添加车厢组成列车;
方法二:直接复制另外一辆已经生成的列车;
在这里插入图片描述
3个getter和toSting方法:用于得到列车的信息;
在这里插入图片描述

3.学习资料LearingMaterials:

在这里插入图片描述
构造函数:
在这里插入图片描述
4个getter和toSting方法:用于得到学习资料的信息;
在这里插入图片描述

3.4 面向复用的设计:Location

在这里插入图片描述

1.Location:用于表示一个具体地点;

在这里插入图片描述
两个构造函数:
在这里插入图片描述
4个setter:
在这里插入图片描述
4个getter:
在这里插入图片描述
toString方法:
在这里插入图片描述

2. MutipleLoaction:有多个地点的计划项使用该类存储地点;

在这里插入图片描述

public void setLocs(LinkedList locs):用于设定一组地址;
在这里插入图片描述
addLocs方法:用于添加一个地址;
在这里插入图片描述
2个getter:以String得到地址的信息;
在这里插入图片描述
toString:用于得到所有地址的信息;
在这里插入图片描述

3. SingleLocation:只有一个地点的计划项使用该类存储地点;

在这里插入图片描述
两个setter:用于设定地址;
在这里插入图片描述
4个getter和toString方法:用于得到地址的信息;
在这里插入图片描述

3.5 面向复用的设计:Timeslot

在这里插入图片描述

1.Time:用于存储一个具体的时间点;

在这里插入图片描述

2.TimeSlot:由两个Time实例组成,构成一个时间段;

在这里插入图片描述
2个Setter:用于设定起始和终止的时间;
在这里插入图片描述
public String getBetweenTime():用于计算并得到,活动时长;
在这里插入图片描述
2个getter:以String的形式得到起始和终止时间的信息;
在这里插入图片描述

3.SingleTime:用于只有一个时间段的计划项的时间存储;

在这里插入图片描述

4.MutipleTime:用于有多个时间段的计划项的时间存储,由一组<TimeSlot,String>组成,String用于存储计划项在该时间段的状态;

在这里插入图片描述
在这里插入图片描述

3.6 面向复用的设计:EntryState及State设计模式

在这里插入图片描述

1.StateEntry:作为所有状态的父类;

通过5个boolean变量来表示不同的状态,isBlocked只有在BLOCKED下才为true,其他状态均为false,可以视为isBlocked仅用于BLOCKED状态中,在其他状态中忽略isBlocked;
在这里插入图片描述
当前状态的getter,以String形式输出状态,分别有:
“WAITING”、“ALLOCATED”、“RUNNING”、“ENDED”、“CANCELLED”、“BLOCKED”,
分别在具体之类中实现;
在这里插入图片描述
5个getter:分别得到当前状态下的五个boolean变量;
在这里插入图片描述

2.Waiting:

isRunning = false;
isAllocated = false;
isEnded = false;
isCancelled = false;
在这里插入图片描述

3.Allocated:

isRunning = false;
isAllocated = true;
isEnded = false;
isCancelled = false;

在这里插入图片描述

4.Running:

isRunning = true;
isAllocated = true;
isEnded = false;
isCancelled = false;
在这里插入图片描述

5.Ended:

isRunning = true;
isAllocated = true;
isEnded = false;
isCancelled = false;
在这里插入图片描述

6.Cancelled:

isCancelled = true;
在这里插入图片描述

7.Blocked:

isBlocked = true;
isRunning = false;
isAllocated = true;
isEnded = false;
isCancelled = false;
在这里插入图片描述

3.7 面向应用的设计:Board

在这里插入图片描述
1.ActivityBoard:
在这里插入图片描述
Activities用于存储一系列的活动计划项;
Time用于存储当前的时间;
Location用于存储Board所展示的活动所处于的地点;
在这里插入图片描述
3个setter和一个add方法用于设置Board的当前状况;
在这里插入图片描述
从所有的计划项中得到活动地点位于Location的计划项;
在这里插入图片描述
在这里插入图片描述
使计划项按照计划开始时间的先后进行排列,是Board更加美观;

public void visualize() {
		JFrame frame = new JFrame("活动计划");

		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		JPanel panel1 = new JPanel();
		panel1.setLayout(new BoxLayout(panel1, BoxLayout.Y_AXIS));

		String s = time.getTime() + ", " + location.getName();
		JLabel label = new JLabel(s, JLabel.CENTER);

		panel1.add(label);

		String[] columnName = new String[] { "时间", "活动名", "状态" };
		ArrayList<String[]> as = new ArrayList<String[]>();

		activitiesSortInTime();

		LinkedList<ActivityEntry> als = searchActivityEntryByLocation();

		for (ActivityEntry al : als) {
			SingleTime st = al.getSt();
			TimeSlot ts = st.getTime();
			if (time.inADay(ts.getBegin()) || time.inADay(ts.getEnd())) {

				String[] s1 = new String[] { ts.getBegin().getHourAndMinute() + "-" + ts.getEnd().getHourAndMinute(),
						al.getPlanningName(), al.getState() };
				as.add(s1);
			}
		}

		String[][] columnDate = (String[][]) as.toArray(new String[0][0]);

		JTable table = new JTable(columnDate, columnName);
		JScrollPane JSP = new JScrollPane(table);
		panel1.add(JSP);

		Container p = frame.getContentPane();
		p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
		frame.add(panel1);

		frame.setSize(800, 400);
		frame.setVisible(true);
	}

在这里插入图片描述

2. FlightBoard:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
将一组航班计划项分别按照出发地和目的地使Location筛选出来;
在这里插入图片描述
得到以Location为目的地的航班的当前状态;
在这里插入图片描述

得到以Location为出发地的航班的当前状态;

public void visualize() {
		JFrame frame = new JFrame("飞机航班");

		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		JPanel panel1 = new JPanel();
		panel1.setLayout(new BoxLayout(panel1, BoxLayout.Y_AXIS));

		String s = time.getTime() + ", " + location.getName();

		JLabel label = new JLabel(s, JLabel.CENTER);

		panel1.add(label);

		JLabel label1 = new JLabel("抵达航班", JLabel.CENTER);
		panel1.add(label1);

		String[] columnName1 = new String[] { "预计抵达时间", "航班号", "出发地-目的地", "状态" };
		ArrayList<String[]> fs1 = new ArrayList<String[]>();

		LinkedList<FlightEntry> fdds = searchFlightEntryByDestination();

		for (FlightEntry fdd : fdds) {
			Time end = fdd.getSingleTime().getTime().getEnd();

			long betweenTimeInMillis = end.getTimeInMillis() - time.getTimeInMillis();

			if (Math.abs(betweenTimeInMillis) <= 1000 * 60 * 60) {
				String state = getddState(fdd, betweenTimeInMillis);
				String[] s1 = new String[] { end.getTime(), fdd.getPlanningName(),
						fdd.getDeparture() + "-" + fdd.getDestination(), state };
				fs1.add(s1);
			}
		}

		String[][] columnDate1 = (String[][]) fs1.toArray(new String[0][0]);

		JTable table1 = new JTable(columnDate1, columnName1);
		JScrollPane JSP1 = new JScrollPane(table1);
		panel1.add(JSP1);

		JPanel panel2 = new JPanel();
		panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));

		JLabel label2 = new JLabel("起飞航班", JLabel.CENTER);
		panel2.add(label2);

		String[] columnName2 = new String[] { "预计起飞时间", "航班号", "出发地-目的地", "状态" };
		ArrayList<String[]> fs2 = new ArrayList<String[]>();

		LinkedList<FlightEntry> fqfs = searchFlightEntryByDeparture();

		for (FlightEntry fqf : fqfs) {
			Time begin = fqf.getSingleTime().getTime().getBegin();

			long betweenTimeInMillis = begin.getTimeInMillis() - time.getTimeInMillis();
			if (Math.abs(betweenTimeInMillis) <= 1000 * 60 * 60) {
				String state = getqfState(fqf, betweenTimeInMillis);
				String[] s2 = new String[] { begin.getTime(), fqf.getPlanningName(),
						fqf.getDeparture() + "-" + fqf.getDestination(), state };
				fs2.add(s2);
			}
		}
		String[][] columnDate2 = (String[][]) fs2.toArray(new String[0][0]);

		JTable table2 = new JTable(columnDate2, columnName2);
		JScrollPane JSP2 = new JScrollPane(table2);
		panel2.add(JSP2);

		Container p = frame.getContentPane();
		p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
		frame.add(panel1);
		frame.add(panel2);

		frame.setSize(800, 400);
		frame.setVisible(true);
	}

在这里插入图片描述

3. TrainBoard:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
从一组高铁车次中筛选出经过Location的车次;

public LinkedHashMap<Integer, String[]> boundaryCondition(TrainEntry train, boolean isCancelled) {
		LinkedHashMap<Integer, String[]> result = new LinkedHashMap<Integer, String[]>();
		MutipleTime mt = train.getMt();
		MutipleLoaction ml = train.getMl();
		String departure = ml.getDeparture();
		String destination = ml.getDestination();
		if (location.getName().equals(departure)) {
			Map.Entry<TimeSlot, String> entry = mt.getTimes().entrySet().iterator().next();
			if ((entry.getKey().getBegin().getTimeInMillis() - time.getTimeInMillis()) <= 1000 * 60 * 60) {
				String s = "已取消";
				if (!isCancelled)
					s = "即将出发";
				String[] s1 = new String[] { entry.getKey().getBeginTime(), train.getPlanningName(),
						departure + "-" + destination, s };
				result.put(1, s1);
			}
			return result;
		}
		if (location.getName().equals(destination)) {
			Iterator<Entry<TimeSlot, String>> entry = mt.getTimes().entrySet().iterator();
			Entry<TimeSlot, String> tail = null;
			while (entry.hasNext()) {
				tail = entry.next();
			}
			if ((time.getTimeInMillis() - tail.getKey().getEnd().getTimeInMillis()) <= 1000 * 60 * 60) {
				String s = "已取消";
				if (!isCancelled)
					s = "已到达";
				String[] s2 = new String[] { tail.getKey().getEndTime(), train.getPlanningName(),
						departure + "-" + destination, s };
				result.put(2, s2);
			}
			return result;
		}
		return result;

public LinkedHashMap<Integer, String[]> boundaryCondition(TrainEntry train, boolean isCancelled):得到以Location为起点或者终点的车次的当前情况;

public LinkedHashMap<Integer, String[]> getState(TrainEntry train, boolean isCancelled) {
		LinkedHashMap<Integer, String[]> result = new LinkedHashMap<Integer, String[]>();
		MutipleTime mt = train.getMt();
		MutipleLoaction ml = train.getMl();
		String departure = ml.getDeparture();
		String destination = ml.getDestination();
		int index = 1;
		for (Map.Entry<TimeSlot, String> entry : mt.getTimes().entrySet()) {
			TimeSlot timeslot = entry.getKey();
			if (timeslot.isIn(time)) {
				if (index % 2 == 0) {
					int i = index / 2;
					Location jt = ml.getByIndex(i);
					if (jt.getName().equals(location.getName())) {
						String s = "已取消";
						if (!isCancelled)
							s = "经停";
						String[] s1 = new String[] { timeslot.getBeginTime(), timeslot.getEndTime(),
								train.getPlanningName(), departure + "-" + destination, s };
						result.put(3, s1);
						return result;
					}
					return result;

				} else {
					int i1 = (index - 1) / 2;
					int i2 = (index + 1) / 2;
					Location cf = ml.getByIndex(i1);
					Location dd = ml.getByIndex(i2);
					if (cf.getName().equals(location.getName())) {
						if ((time.getTimeInMillis() - timeslot.getBegin().getTimeInMillis()) <= 1000 * 60 * 60) {
							String s = "已取消";
							if (!isCancelled)
								s = "已出发";
							String[] s2 = new String[] { timeslot.getBeginTime(), train.getPlanningName(),
									departure + "-" + destination, s };
							result.put(2, s2);
						}
						return result;

					}
					if (dd.getName().equals(location.getName())) {
						if ((timeslot.getEnd().getTimeInMillis() - time.getTimeInMillis()) <= 1000 * 60 * 60) {
							String s = "已取消";
							if (!isCancelled)
								s = "即将到达";
							String[] s3 = new String[] { timeslot.getEndTime(), train.getPlanningName(),
									departure + "-" + destination, s };
							result.put(1, s3);
						}
						return result;
					}
					return result;
				}
			}
			index++;
		}
		return result;
	}

public LinkedHashMap<Integer, String[]> getState(TrainEntry train, boolean isCancelled):得到不以Location为起点或终点,但是经过Location的车次的当前情况;

public void visualize() {
		JFrame frame = new JFrame("高铁车次");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		JPanel panel1 = new JPanel();
		panel1.setLayout(new BoxLayout(panel1, BoxLayout.Y_AXIS));

		String s = time.getTime() + ", " + location.getName();
		JLabel label = new JLabel(s, JLabel.CENTER);
		panel1.add(label);

		JLabel label1 = new JLabel("抵达车次", JLabel.CENTER);
		panel1.add(label1);

		JPanel panel2 = new JPanel();
		panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS));
		JLabel label2 = new JLabel("出发车次", JLabel.CENTER);
		panel2.add(label2);

		JPanel panel3 = new JPanel();
		panel3.setLayout(new BoxLayout(panel3, BoxLayout.Y_AXIS));
		JLabel label3 = new JLabel("经停车次", JLabel.CENTER);
		panel3.add(label3);

		LinkedList<TrainEntry> psts = searchPassByTrains();

		String[] columnName1 = new String[] { "抵达时间", "车次", "出发地-目的地", "状态" };
		ArrayList<String[]> ts1 = new ArrayList<String[]>();

		String[] columnName2 = new String[] { "出发时间", "车次", "出发地-目的地", "状态" };
		ArrayList<String[]> ts2 = new ArrayList<String[]>();

		String[] columnName3 = new String[] { "到达时间", "出发时间", "车次", "出发地-目的地", "状态" };
		ArrayList<String[]> ts3 = new ArrayList<String[]>();

		for (TrainEntry pst : psts) {
			boolean isCancelled = false;
			if (pst.getState().equals("CANCELLED"))
				isCancelled = true;
			Map<Integer, String[]> result1 = boundaryCondition(pst, isCancelled);
			if (result1.isEmpty()) {
				Map<Integer, String[]> result2 = getState(pst, isCancelled);
				if (result2.isEmpty())
					continue;
				else {
					Map.Entry<Integer, String[]> entry = result2.entrySet().iterator().next();
					int state = entry.getKey();
					if (state == 1)
						ts1.add(entry.getValue());
					if (state == 2)
						ts2.add(entry.getValue());
					if (state == 3)
						ts3.add(entry.getValue());
				}
			} else {
				Map.Entry<Integer, String[]> entry = result1.entrySet().iterator().next();
				int state = entry.getKey();
				if (state == 2)
					ts1.add(entry.getValue());
				if (state == 1)
					ts2.add(entry.getValue());

			}
		}

		String[][] columnDate1 = (String[][]) ts1.toArray(new String[0][0]);
		String[][] columnDate2 = (String[][]) ts2.toArray(new String[0][0]);
		String[][] columnDate3 = (String[][]) ts3.toArray(new String[0][0]);

		JTable table1 = new JTable(columnDate1, columnName1);
		JScrollPane JSP1 = new JScrollPane(table1);
		panel1.add(JSP1);

		JTable table2 = new JTable(columnDate2, columnName2);
		JScrollPane JSP2 = new JScrollPane(table2);
		panel2.add(JSP2);

		JTable table3 = new JTable(columnDate3, columnName3);
		JScrollPane JSP3 = new JScrollPane(table3);
		panel3.add(JSP3);

		Container p = frame.getContentPane();
		p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
		frame.add(panel1);
		frame.add(panel2);
		frame.add(panel3);

		frame.setSize(1000, 400);
		frame.setVisible(true);

	}

在这里插入图片描述

3.8 Board的可视化:外部API的复用

已经在3.7中进行描述

3.9 PlanningEntryCollection的设计

3.10 可复用API设计及Façade设计模式

3.10.1 检测一组计划项之间是否存在位置独占冲突

3.10.2 检测一组计划项之间是否存在资源独占冲突

3.10.3 提取面向特定资源的前序计划项

3.11 设计模式应用

3.11.1 Factory Method

3.11.2 Iterator

3.11.3 Strategy

3.12 应用设计与开发

3.12.1 航班应用

Flights用于存储当前的航班计划项;
Locs用于存储当前可用的地址;
Acs用于存储当前可用的飞机资源;
在这里插入图片描述

用于得到用户的输入;
在这里插入图片描述

用于设定某个计划项中的时间;
在这里插入图片描述
用于设定某个计划项中的出发地和目的地;
在这里插入图片描述
从谁当某个计划项中的飞机资源;
在这里插入图片描述

用于可用飞机资源的增加或删除;
在这里插入图片描述

用于可用地址的增加或删除;
在这里插入图片描述
用于判断某个计划项是否在当前计划项列表中;
在这里插入图片描述
操作:
在这里插入图片描述

public void app() {
		System.out.println("Operation list:");
		System.out.println("1.Add location;");
		System.out.println("2.Delete location;");
		System.out.println("3.Add aircraft resources;");
		System.out.println("4.Delete aircraft resources;");
		System.out.println("5.Add flight plan item;");
		System.out.println("6.Assign resources to a flight plan item;");
		System.out.println("7.Cancel a flight plan item;");
		System.out.println("8.Start a flight plan item;");
		System.out.println("9.End a flight plan item;");
		System.out.println("10.Get the current status of a flight plan item;");
		System.out.println("11.Check whether there is position conflict in all current flight plan items;");
		System.out.println("12.Check whether there are resource conflicts in all current flight plan items;");
		System.out.println("13.Get the first flight of a flight;");
		System.out.println("14.Generate flight planning board according to a certain location;");
		System.out.println("15.Exit;");
		do {
			int operation = Integer.parseInt(getInput("Please enter the operation"));
			switch (operation) {
			case 1:
				addLoc();
				break;
			case 2:
				deleteLocs();
				break;
			case 3:
				addAcs();
				break;
			case 4:
				deleteAcs();
				break;
			case 5:
				addFlight();
				break;
			case 6:
				allocatedFlights();
				break;
			case 7:
				deleteFlights();
				break;
			case 8:
				runningFlights();
				break;
			case 9:
				endFlights();
				break;
			case 10:
				System.out.println(getState());
				break;
			case 11:
				if (checkLocationConflict())
					System.out.println("Location Conflict!");
				else
					System.out.println("No Location Conflict!");
				break;
			case 12:
				if (checkResourceExclusiveConflict())
					System.out.println("Resource Exclusive Conflict!");
				else
					System.out.println("No Resource Exclusive Conflict!");
				break;
			case 13:
				System.out.println(findPreEntryPerResource().toString());
				break;
			case 14:
				showBoard();
				break;
			case 15:
				System.exit(0);
			default:
				System.out.println("Input Wrong!");
				break;
			}
		} while (true);

	}

3.12.2 高铁应用

与之前类似的方法就不进行重复描述,只描述该应用中出现的特有方法;
在这里插入图片描述
通过用户输入设定一个列车车厢;
在这里插入图片描述
通过用户输入设定一列列车;
在这里插入图片描述
用于设定某个计划项的时间;
在这里插入图片描述
用于设定某个计划项的地址;
在这里插入图片描述
增加的特有操作;
在这里插入图片描述

public void app() {
		System.out.println("Operation list:");
		System.out.println("1.Add location;");
		System.out.println("2.Delete location;");
		System.out.println("3.Add aircraft resources;");
		System.out.println("4.Delete aircraft resources;");
		System.out.println("5.Add flight plan item;");
		System.out.println("6.Assign resources to a flight plan item;");
		System.out.println("7.Cancel a flight plan item;");
		System.out.println("8.Start a flight plan item;");
		System.out.println("9.End a flight plan item;");
		System.out.println("10.Get the current status of a flight plan item;");
		System.out.println("11.Check whether there is position conflict in all current flight plan items;");
		System.out.println("12.Check whether there are resource conflicts in all current flight plan items;");
		System.out.println("13.Get the first flight of a flight;");
		System.out.println("14.Generate flight planning board according to a certain location;");
		System.out.println("15.Block a flight plan item;");
		System.out.println("16.Restrat a flight plan item;");
		System.out.println("17.Exit;");
		do {
			int operation = Integer.parseInt(getInput("Please enter the operation"));
			switch (operation) {
			case 1:
				addLoc();
				break;
			case 2:
				deleteLocs();
				break;
			case 3:
				addTs();
				break;
			case 4:
				deleteTs();
				break;
			case 5:
				addTrains();
				break;
			case 6:
				allocatedTrains();
				break;
			case 7:
				cancelledTrains();
				break;
			case 8:
				runningTrains();
				break;
			case 9:
				endTrains();
				break;
			case 10:
				System.out.println(getState());
				break;
			case 11:
				if (checkLocationConflict())
					System.out.println("Location Conflict!");
				else
					System.out.println("No Location Conflict!");
				break;
			case 12:
				if (checkResourceExclusiveConflict())
					System.out.println("Resource Exclusive Conflict!");
				else
					System.out.println("No Resource Exclusive Conflict!");
				break;
			case 13:
				System.out.println(findPreEntryPerResource().toString());
				break;
			case 14:
				showBoard();
				break;
			case 15:
				blockedTrains();
				break;
			case 16:
				runningTrains();
				break;
			case 17:
				System.exit(0);
			default:
				System.out.println("Input Wrong!");
				break;
			}
		} while (true);

	}

3.12.3 进程应用

3.12.4 课表应用

3.12.5 学习活动应用

在这里插入图片描述
增加的特有操作;
在这里插入图片描述

3.13 基于语法的数据读入

public void readFromFile() {
		int i = Integer.parseInt(getInput("Please enter the number of files to read in"));
		ArrayList<String> arrayList = new ArrayList<>();
		String name = "src/txt/FlightSchedule_" + String.format("%d", i) + ".txt";
		File file = new File(name);
		try {
			FileReader fr = new FileReader(file);
			BufferedReader bf = new BufferedReader(fr);
			String str;
			while ((str = bf.readLine()) != null) {
				arrayList.add(str);
			}
			bf.close();
			fr.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		int length = arrayList.size();
		for (int x = 0; x < length; x = x + 13) {
			int y = 0;
			String l1 = arrayList.get(x + y);
			String[] l11 = l1.split(",");
			String planningName = l11[1];

			y++;

			y++;
			String l3 = arrayList.get(x + y);
			String[] l31 = l3.split(":");
			String departAirport = l31[1];
			Location departure = new Location();
			departure.setName(departAirport);
			departure.setIsShareAble(true);

			y++;
			String l4 = arrayList.get(x + y);
			String[] l41 = l4.split(":");
			String arrivalAirport = l41[1];
			Location arrival = new Location();
			arrival.setName(arrivalAirport);
			arrival.setIsShareAble(true);

			y++;
			String l5 = arrayList.get(x + y);
			String[] l51 = l5.split("\\s+");
			String[] l52 = l51[1].split(":");
			int hour = Integer.parseInt(l52[0]);
			int minute = Integer.parseInt(l52[1]);
			String[] l53 = l51[0].split(":");
			String[] l54 = l53[1].split("-");

			int year = Integer.parseInt(l54[0]);
			int month = Integer.parseInt(l54[1]);
			int day = Integer.parseInt(l54[2]);

			Time begin = new Time(year, month, day, hour, minute);

			y++;
			String l6 = arrayList.get(x + y);
			String[] l61 = l6.split("\\s+");
			String[] l62 = l61[1].split(":");
			int hour1 = Integer.parseInt(l62[0]);
			int minute1 = Integer.parseInt(l62[1]);
			String[] l63 = l61[0].split(":");
			String[] l64 = l63[1].split("-");

			int year1 = Integer.parseInt(l64[0]);
			int month1 = Integer.parseInt(l64[1]);
			int day1 = Integer.parseInt(l64[2]);

			Time end = new Time(year1, month1, day1, hour1, minute1);

			TimeSlot st = new TimeSlot(begin, end);

			y++;
			String l7 = arrayList.get(x + y);
			String[] l71 = l7.split(":");
			String number = l71[1];

			y++;

			y++;
			String l9 = arrayList.get(x + y);
			String[] l91 = l9.split(":");
			String type = l91[1];

			y++;
			String l10 = arrayList.get(x + y);
			String[] l101 = l10.split(":");
			int seating = Integer.parseInt(l101[1]);

			y++;
			String s11 = arrayList.get(x + y);
			String[] s111 = s11.split(":");
			double age = Double.parseDouble(s111[1]);
			
			Aircraft a = new Aircraft(number, type, seating, age);

			FlightEntry fe = new FlightEntry(planningName, st, departure, arrival);
			fe.planningAllocated(a);
			
			flights.add(fe);
		}
	}

3.14 应对面临的新变化

3.14.1 变化1

航班支持经停
原来的:
在这里插入图片描述
参数中的改变,只需要将存储时间的参数st类变为MutipleTime
改变后:
在这里插入图片描述
如何将st的setter和getter进行相应的改变;
原来的Getter:
在这里插入图片描述
改变后:只需要改变返回值
在这里插入图片描述
原来的Setter:是调用SingleTime类中方法进行赋值
在这里插入图片描述
改变后的Setter:调用MutipleTime中类的方法进行赋值,可以直接复制TrainEntry中的方法,因为现在两者存储时间的类型都是MutipleTime,设置时间的操作相同,只是添加多少时间对不一样而已,并且将调用改变后setter的方法相应的接口进行改变即可;
在这里插入图片描述
但是由于之前的测试函数是按照无经停情况进行编写的,需要将测试函数重新编写;
还需要再FlightEntry中加入blocked状态对应的方法,变化方法与变化3类似,因此在变化3中在进行仔细讲解,现在就给出个结果。
添加public boolean planningBlocked():
在这里插入图片描述
重写其父类CommonPlanningEntry中的方法public boolean planningCancelled():
在这里插入图片描述

3.14.2 变化2

高铁车次分配了列车后,无法取消;
原来的:位于CommonPlanningEntry类中;
在这里插入图片描述

在这里插入图片描述
改变后:在TrainEntry类中重写该方法
在这里插入图片描述
在这里插入图片描述

3.14.3 变化3

活动执行后可以阻塞
在ActivityEntry类中增加一个方法public boolean planningBlocked():
在这里插入图片描述
在ActivityEntry类中重写其父类CommonPlanningEntry中的方法public boolean planningCancelled()
在这里插入图片描述
由于TrainEntry现在的状态转移图跟ActivityEntry一致,两个方法均可以从TrainEntry中直接复制。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值