2020年春季学期
计算机学院《软件构造》课程

Lab 3实验报告
1 实验目标概述 1
2 实验环境配置 1
3 实验过程 1
3.1 待开发的三个应用场景 1
3.2 面向可复用性和可维护性的设计:PlanningEntry 1
3.2.1 PlanningEntry的共性操作 1
3.2.2 局部共性特征的设计方案 2
3.2.3 面向各应用的PlanningEntry子类型设计(个性化特征的设计方案) 2
3.3 面向复用的设计:R 2
3.4 面向复用的设计:Location 2
3.5 面向复用的设计:Timeslot 2
3.6 面向复用的设计:EntryState及State设计模式 2
3.7 面向应用的设计:Board 2
3.8 Board的可视化:外部API的复用 2
3.9 可复用API设计及Façade设计模式 2
3.9.1 检测一组计划项之间是否存在位置独占冲突 2
3.9.2 检测一组计划项之间是否存在资源独占冲突 2
3.9.3 提取面向特定资源的前序计划项 2
3.10 设计模式应用 2
3.10.1 Factory Method 3
3.10.2 Iterator 3
3.10.3 Strategy 3
3.11 应用设计与开发 3
3.11.1 航班应用 3
3.11.2 高铁应用 3
3.11.3 进程应用 3
3.11.4 课表应用 3
3.11.5 学习活动应用 3
3.12 基于语法的数据读入 3
3.13 应对面临的新变化 3
3.13.1 变化1 3
3.13.2 变化2 4
3.13.3 变化3 4
3.14 Git仓库结构 4
4 实验进度记录 4
5 实验过程中遇到的困难与解决途径 4
6 实验过程中收获的经验、教训、感想 5
6.1 实验过程中收获的经验和教训 5
6.2 针对以下方面的感受 5

1 实验目标概述
本次实验覆盖课程第 3、4、5 章的内容,目标是编写具有可复用性和可维护性的软件,主要使用以下软件构造技术:

子类型、泛型、多态、重写、重载
继承、代理、组合
常见的 OO 设计模式
语法驱动的编程、正则表达式
基于状态的编程
API 设计、API 复用

本次实验给定了五个具体应用(高铁车次管理、航班管理、操作系统进程管理、大学课表管理、学习活动日程管理),学生不是直接针对五个应用分别编程实现,而是通过 ADT 和泛型等抽象技术,开发一套可复用的 ADT 及其实现,充分考虑这些应用之间的相似性和差异性,使 ADT 有更大程度的复用(可复用性)和更容易面向各种变化(可维护性)。
2 实验环境配置
在这里给出你的GitHub Lab3仓库的URL地址(Lab3-学号)。
https://github.com/ComputerScienceHIT/Lab3-1180300625
3 实验过程
请仔细对照实验手册,针对每一项任务,在下面各节中记录你的实验过程、阐述你的设计思路和问题求解思路,可辅之以示意图或关键源代码加以说明(但千万不要把你的源代码全部粘贴过来!)。
3.1 待开发的三个应用场景
我选择的三个应用场景:
• 航班管理
• 高铁车次管理
• 大学课表管理
异同点:
位置的数量:分别为2个、N个和1个
仅有大学课表的位置可更改
航班为单个资源,高铁为有序多个资源,大学课表为无序多个资源
仅有高铁车次可阻塞
3.2 面向可复用性和可维护性的设计:PlanningEntry
该节是本实验的核心部分。
3.2.1 PlanningEntry的共性操作
/**
* 开始计划项
*/
public void start();

/*** 取消计划项*/
public void cancel();/*** 完成计划项*/
public void complete();/*** 分配计划项*/
public void provide();/*** 获得计划项名称* * @return 字符串类型的计划项名称*/
public String getid();/*** 获得计划项状态* * @return 字符串类型的计划项状态*/
public String getstate();/*** 获得计划项在某位置处的预订时间对* * @param 位置* @return 计划项在该位置处的预订时间对*/
public Lot_time getTimeslot(Location location);/*** 创建计划项* * @param 计划项名称* @param 计划项类型,1为航班,2为高铁,4为课程* @return 一个计划项实例*/
public static <R> CPEimlements<Resource> create(String id, int intType)

3.2.2 局部共性特征的设计方案
public abstract class CommonPlanEntry implements CPEimlements {
protected EntryState estate = WaitState.getInstance();

@Override
public void provide() {if (this.estate.toString().equals("Waiting"))this.estate = estate.nextState();elseassert false;}

方法也都是采用状态模式进行状态转换
3.2.3 面向各应用的PlanningEntry子类型设计(个性化特征的设计方案)
采用方案 5:CRP,通过接口组合实现局部共性特征的复用:针对方案4,通过delegation 机制进行改造。每个维度分别定义自己的接口,针对每个维度的不同特征取值,分别实现针对该维度接口的不同实现类,实现其特殊操作逻辑。进而,通过接口组合,将各种局部共性行为复合在一起,形成满足每个应用要求的特殊接口(包含了该应用内的全部特殊功能),从而该应用子类可直接实现该组合接口。在应用子类内,不是直接实现每个特殊操作,而是通过 delegation 到外部每 个维度上的各具体实现类的相应特殊操作逻辑。

public class CourseEntry extends CommonPlanEntry implements CoursePlanEntry {
private ALEImplements sin1;
private AREImplements sin2;
private ATEImplements sin3;
private ChangeableLocationEntry cha;
private final String id;

// Abstraction function:
// sin1, sin2,sin3,cha,id分别表示课程为单个位置,单个资源,单个时间对,可变位置,课程名
// Representation invariant:
// sin1, sin2,sin3,id不能为null
// Safety from rep exposure:
// 所有属性均为private,id设为private

public class FlightEntry extends CommonPlanEntry implements FlightPlanEntry {
private TLEImplements tle;
private AREImplements arei;
private ATEImplements atei;
private final String id;

// Abstraction function:
// tle, arei,atei,id分别表示课程为两个位置,单个资源,单个时间对,航班名
// Representation invariant:
// tle, arei,atei,id不能为null
// Safety from rep exposure:
// 所有属性均为private,id设为private

public class TrainEntry extends CommonPlanEntry implements TrainPlanningEntry {
private MLElmplements mle;
private BEImplements bei;
private MTEImplements mte;
private MREImplements mre;
private final String id;

// Abstraction function:
// mle,be, msre,mte,id分别表示课程为多个位置,可被阻塞,多个资源,多个时间对,高铁车次
// Representation invariant:
// mle,be, msre,mte,id不能为null
// Safety from rep exposure:
// 所有属性均为private,id设为private

public interface TrainPlanningEntryextendsManyLocationEntry,BlockableEntry, ManyResourceEntry, ManyTimeEntry {

接口大多相同,返回值的区别很小。
3.3 面向复用的设计:R
@Override
public boolean equals(Object obj);
/**
* 获得一个自己的相同的资源
*
* @return Resource类型的自己的clone
/
public Resource getResourece();
/
*
* 获得一个资源的标志,例如名字
*
* @return 自己的最有特征的标志
*/
public String getbiaozhi() ;

/**

  • 车厢类型的资源,不可变类
    */
    public final class Carriage implements Resource {
    private final String ID, type;
    private final int capacity, year;

    // Abstraction function:
    // number, type, capacity, year分别表示车厢的编号,类型,定员数,出厂年份
    // Representation invariant:
    // 车厢编号不能为null,定员数,出厂年份是正数
    // Safety from rep exposure:
    // 所有属性均为private final

/**

  • 飞机类型的资源,不可变类
    */
    public final class Plane implements Resource {
    private final String ID, model;
    private final int seats,age;

    // Abstraction function:
    // ID, model, seats,age分别表示飞机的编号,机型号,座位数,机龄
    // Representation invariant:
    // 飞机编号不能为null,座位数和机龄是正数
    // Safety from rep exposure:
    // 所有属性均为private final
    /**

  • 教师类型的资源,不可变类
    */
    public final class Teacher implements Resource {
    private final String ID, name, position;
    private final boolean sex;

    // Abstraction function:
    // ID, name, position分别表示教师的编号,姓名,职称
    // sex为true表示该教师性别为男,false为女
    // Representation invariant:
    // 教师姓名和身份证号不能为null
    // Safety from rep exposure:
    // 所有属性均为private final
    3.4 面向复用的设计:Location
    /**

  • 位置
    /
    public interface Location {
    /
    *

    • 获得该位置的地址名
    • @return String类型的该位置的地址名
      /
      public String getPlace();
      /
      *
    • 获得相同的位置
    • @return Location类型位置的clone
      */
      public Location getLocation();
      @Override
      public boolean equals(Object obj);
      }

/**

  • 机场,不可变类
    */
    public final class Airport implements Location {

    private final String longitude, latitude, name;
    private final boolean share;

    // Abstraction function:
    // longitude,latitude,place分别表示机场所在位置的经度,纬度,机场名
    // Share 表示机场是否可共享
    // Representation invariant:
    // 机场名不能为null,Share为true
    // Safety from rep exposure:
    // 所有属性均为private final
    /**

  • 教室,不可变类
    */
    public final class Classroom implements Location {
    private final String longitude, latitude, name;
    private final boolean share;

    // Abstraction function:
    // longitude,latitude,place分别表示教室所在位置的经度,纬度,教室名
    // Share 表示教室是否可共享
    // Representation invariant:
    // 教室名不能为null,Share为false
    // Safety from rep exposure:
    // 所有属性均为private final

/**

  • 高铁站,不可变类
    */

public class Trainstation implements Location {
private final String longitude, latitude, name;
private final boolean share;

// Abstraction function:
// longitude,latitude,place分别表示高铁站所在位置的经度,纬度,机场名
// Share 表示高铁站是否可共享
// Representation invariant:
// 高铁站不能为null,Share为true
// Safety from rep exposure:
// 所有属性均为private final

3.5 面向复用的设计:Timeslot
/**

  • 起止时间,不可变类
    */
    public final class Lot_time {
    private final Calendar start, end;

    // Abstraction function:
    // start, end分别表示起止时间
    // Representation invariant:
    // 开始时间,结束时间不为空
    // Safety from rep exposure:
    // 所有属性均为private final
    public Lot_time(Calendar start, Calendar end) {
    this.start = start;
    this.end = end;
    checkRep();
    }

    /**

    • 获得开始时间
    • @return Calendar 开始时间
      */
      public Calendar getStartTime() {
      return (Calendar) start.clone();
      }

    /**

    • 获得结束时间
    • @return Calendar 结束时间
      */
      public Calendar getEndTime() {
      return (Calendar) end.clone();
      }

    // checkRep
    public void checkRep() {
    assert !(start == null || end == null);
    }
    3.6 面向复用的设计:EntryState及State设计模式

/**

  • 一个能够改变状态和获得状态的接口
    /
    public interface EntryState {
    /
    *

    • 向下进行下一个状态 *
    • @return 一个新状态的接口
      /
      public EntryState nextState();
      /
      *
    • 撤销或阻塞一个状态
    • @return 一个新状态的接口
      /
      public EntryState cancleState();
      /
      *
    • 获得当前状态的信息
    • @return 字符串类型的当前状态信息
      */
      3.7 面向应用的设计:Board
      import java.util.List;

import Entry.PlanningEntry.CPEimlements;
import Resource.Resource;
/**

  • 将计划项可视化
    /
    public interface Board {
    /
    *

    • 将此处的计划项可视化

    /
    public void display();
    /
    *

    • 选择与自身位置匹配的计划项,加到可视化计划项列表中
    • @param List<PlanEntry> 一组计划项
      */
      public void add(List<CPEimlements> entry);

*课程的可视化
*/
public class CourseBoard implements Board {
private final Location location;
private List<CPEimlements> entry;

// Abstraction function:
// location, entry分别表示位置与在此位置处的计划项集合
// Representation invariant:
// location不能为空
// Safety from rep exposure:
// location为private final,entries为private

/**

  • 航班的可视化
    */
    public class FlightBoard implements Board {
    private final Location location;
    private List<CPEimlements> entry;
    private static final int range = 1;
    public static final int arrive = 1;
    public static final int leave = -1;
    // Abstraction function:
    // location, entry分别表示位置与在此位置处的计划项集合
    // Representation invariant:
    // location不能为空
    // Safety from rep exposure:
    // location为private final,entries为private

/**

  • 高铁的可视化
    */
    public class TrainBoard implements Board {
    private final Location location;
    private List<CPEimlements> entry;
    private static final int range = 1;
    public static final int arrive = 1;
    public static final int leave = -1;

    // Abstraction function:
    // location, entry分别表示位置与在此位置处的计划项集合
    // Representation invariant:
    // location不为空
    // Safety from rep exposure:
    // location为private final,entries为private
    3.8 Board的可视化:外部API的复用

调用public class Create extends JFrame{
public Create(String xinxi,Vector<Vector<?>> data, Vector name) {
table = new JTable(data, name);
scrollpane = new JScrollPane(table);
setTitle(xinxi);
setBounds(300,300,400,400);
setVisible(true);
add(scrollpane,BorderLayout.CENTER);
}
3.9 可复用API设计及Façade设计模式
3.9.1 检测一组计划项之间是否存在位置独占冲突
public boolean CLConflict(List<CPEimlements> entry) {
for(CPEimlements cpei1 : entry) {
for (CPEimlements cpei2 : entry) {
CoursePlanEntry cpe1=(CoursePlanEntry)cpei1;
CoursePlanEntry cpe2=(CoursePlanEntry)cpei2;
if(cpei1.getid().equals(cpei2.getid()))
continue;
if(cpe1.getEntryLocation().equals(cpe2.getEntryLocation()))
{
Calendar cpe1time = cpe1.getTime().getStartTime();
Calendar cpe2time = cpe2.getTime().getStartTime();
Calendar cpe1etime = cpe1.getTime().getEndTime();
Calendar cpe2etime = cpe2.getTime().getEndTime();
if (!(cpe1time.after(cpe2etime) || cpe1etime.before(cpe2time)))
return false;
}
}
}
return true;
}
三个都差不多,故只放一个
3.9.2 检测一组计划项之间是否存在资源独占冲突
public boolean CRConflict(List<CPEimlements> entry) {
for (CPEimlements cpei1 : entry)
for (CPEimlements cpei2 : entry) {
CoursePlanEntry cpe2 = (CoursePlanEntry) cpei2;
CoursePlanEntry cpe1 = (CoursePlanEntry) cpei1;
if(cpei1.getid().equals(cpei2.getid())||cpe1.getResource()==null||cpe2.getResource()==null)
continue;
if (cpe2.getResource().equals(cpe1.getResource())) {
Calendar cpe1time = cpe1.getTime().getStartTime();
Calendar cpe2time = cpe2.getTime().getStartTime();
Calendar cpe1etime = cpe1.getTime().getEndTime();
Calendar cpe2etime = cpe2.getTime().getEndTime();
if (!(cpe1time.after(cpe2etime) || cpe1etime.before(cpe2time)))
return false;
}
}
return true;
}
3.9.3 提取面向特定资源的前序计划项
public CPEimlements FEResource(Resource r, CPEimlements cpei,List<CPEimlements> entry) {
CoursePlanEntry cpe1 = (CoursePlanEntry) cpei;
for (CPEimlements cpei2 : entry) {
CoursePlanEntry cpe2 = (CoursePlanEntry) cpei2;
if (cpe2.getResource().equals®) {
if (cpe2.getTime().getStartTime().before(cpe1.getTime().getStartTime())) {
return cpei2;
}
}
}
return null;
}
3.10 设计模式应用
请分小节介绍每种设计模式在你的ADT和应用设计中的具体应用。
3.10.1 Factory Method
3.10.2 Iterator
Vector<Vector<?>> data = new Vector<>();
Vector name = new Vector<>();
Iterator<CPEimlements> hmx = entry.iterator();
Sort sort;
sort = new ShellSort();
sort.shell(entry, location, type);
3.10.3 Strategy
/**

  • 希尔排序
    */
    public class ShellSort implements Sort {

    @Override
    public void shell(List<CPEimlements> entry, Location location, int type) {
    int i, j, k;

为数据进行排序
3.11 应用设计与开发
利用上述设计和实现的ADT,实现手册里要求的各项功能。
只需保留你选定的三个应用即可。
3.11.1 航班应用

3.11.2 高铁应用

3.11.3 进程应用
3.11.4 课表应用

3.11.5 学习活动应用
3.12 基于语法的数据读入
依据给定数据的格式,可以设计正则表达式,并保存在Pattern对象中。
“Flight:(.?),([A-Z]{2}\d{2,4})\n\{\nDepartureAirport:(\w+)\nArrivalAirport:(\w+)\nDepatureTime:(.?)\nArrivalTime:(.?)\nPlane:((N|B)\d{4})\n\{\nType:([a-zA-Z0-9]+)\nSeats:(.?)\nAge:((0|(([1-9])\d))(\.\d)?)\n\}\n\}\n”)

判读异常
异常就由顶层方法捕获,打印文件格式不符合的信息,把现有的计划项返回
反之就把新建的航班加入到计划项集合中

3.13 应对面临的新变化
只考虑你选定的三个应用的变化即可。
3.13.1 变化1
将航班的实现类的接口的继承由之前的TwoLocationEntry改为ThreeLocationEntry

3.13.2 变化2
课程:把接口继承由之前的SingleSortedResourceEntry改为MultipleSortedResourceEntry
3.13.3 变化3
高铁:把父类commonPlanningEntry中的cancel重写一下即可,让只有未分配与阻塞状态可取消

3.14 Git仓库结构
请在完成全部实验要求之后,利用Git log指令或Git图形化客户端或GitHub上项目仓库的Insight页面,给出你的仓库到目前为止的Object Graph,尤其是区分清楚314change分支和master分支所指向的位置。
6.2 针对以下方面的感受
(1) 重新思考Lab2中的问题:面向ADT的编程和直接面向应用场景编程,你体会到二者有何差异?本实验设计的ADT在五个不同的应用场景下使
用,你是否体会到复用的好处?
答:前者得先思考框架前期麻烦但是后期会变得更方便,后者前期可以随心所欲地写,但越到后面需要小心的地方就越多,出现问题多的话可能得重新开始写代码。修改和使用非常方便。
(2) 重新思考Lab2中的问题:为ADT撰写复杂的specification, invariants, RI,
AF,时刻注意ADT是否有rep exposure,这些工作的意义是什么?你是否愿意在以后的编程中坚持这么做?
答:帮助作者或者使用代码的人快速理解代码。愿意因为这个可以减少我花费的时间。
(3) 之前你将别人提供的API用于自己的程序开发中,本次实验你尝试着开发给别人使用的API,是否能够体会到其中的难处和乐趣?
答:深深的体会到了难处。
(4) 在编程中使用设计模式,增加了很多类,但在复用和可维护性方面带来了收益。你如何看待设计模式?
答:刚开始建的时候很难,但是后来就会很好用。
(5) 你之前在使用其他软件时,应该体会过输入各种命令向系统发出指令。本次实验你开发了一个解析器,使用语法和正则表达式去解析输入文件并据此构造对象。你对语法驱动编程有何感受?
答:考虑的东西非常多,一错就是一大片。
(6) Lab1和Lab2的大部分工作都不是从0开始,而是基于他人给出的设计方案和初始代码。本次实验是你完全从0开始进行ADT的设计并用OOP实现,经过五周之后,你感觉“设计ADT”的难度主要体现在哪些地方?你是如何克服的?
答:主要难在框架的构建。我向很多同学咨询了。
(7) “抽象”是计算机科学的核心概念之一,也是ADT和OOP的精髓所在。本实验的五个应用既不能完全抽象为同一个ADT,也不是完全个性化,如何利用“接口、抽象类、类”三层体系以及接口的组合、类的继承、设计模式等技术完成最大程度的抽象和复用,你有什么经验教训?
答:熟练掌握接口的使用能让代码复用率变高,代码量减少。
(8) 关于本实验的工作量、难度、deadline。
答:工作量很大,难度其次。就是需要一直不厌其烦的修改。
(9) 到目前为止你对《软件构造》课程的评价。
答:学到很多的知识,但难度很大,很有挑战。

哈工大软件构造lab3相关推荐

  1. 2021哈工大软件构造Lab3

    2021年春季学期 计算学部<软件构造>课程 Lab 3实验报告 实验源码:https://github.com/1190200817/SC_Lab3 目录 1 实验目标概述··· 1 2 ...

  2. 哈工大软件构造lab3总结

    软构的课程已经结束一段落了,如今回顾起来,收获颇丰.这篇博客主要是回顾一下lab3自己出现的一些问题,总结一下教训,帮接下来需要做实验的同学们避避坑. 第一点:不要拖延症,不要拖延症,不要拖延症. 不 ...

  3. 哈工大-软件构造-Lab3(1)

    前言 好不容易完成了Lab3的实验,有送走了计算方法和信息安全,再写lab4的时候,抽出点功夫不补一下lab3的博客,由于的确时间有点久,有些问题记不太清了,就想到啥写啥吧 程序的设计 第一个想到的就 ...

  4. 哈工大2022软件构造Lab3

    说明 此博客内容为哈工大2022春季学期软件构造Lab3:Reusability and Maintainability oriented Software Construction,文章为个人记录, ...

  5. 哈工大软件构造期末知识点总结

    哈工大软件构造试题构成: 1.30-45分的选择题,10-20题 2.55-70分的简答与设计题,5-6题 考试知识点(不全面): 1.git工具的知识点 2.Java设计模式(一共有23个,主要考察 ...

  6. 软件构造 Lab3 CircularOrbit 实验日记

    软件构造 Lab3 CircularOrbit 实验日记 SC Lab3 CircularOrbit 实验日记(持更)week6-week10 日期 时间段 计划任务 实际完成情况 2019-04-0 ...

  7. 2022哈工大软件构造lab1小结(知识点)

    哈工大软件构造lab1小结 提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 问题一 使用的库 异常处理机制 字符串内容检查 写入文件 问题二 problem 3:画一 ...

  8. 哈工大软件构造 复习

    哈工大软件构造试题构成: 1.30分的选择题 2.70分的简答题 2019考试知识点(重要的,但不涵盖全部考试范围): 1.git工具的知识点(没有考察命令行,考察的主要是git的演变及各部分的作用) ...

  9. 哈工大软件构造课程知识点总结(一)

    系列文章目录 哈工大软件构造课程知识点总结(一) 哈工大软件构造课程知识点总结(二) 哈工大软件构造课程知识点总结(三) 哈工大软件构造课程知识点总结(四) 哈工大软件构造课程知识点总结(五) 哈工大 ...

最新文章

  1. 遗传算法c语言程序,遗传算法c语言代码.doc
  2. 华山论剑之iOStableView的双剑合璧
  3. 《迷人的8051单片机》----3.4 程序
  4. C sharp实例:华盾武器门数据接收和解析
  5. JAVA day06 继承,super,方法的重写,抽象类
  6. HTML 列表 olullidldtdd
  7. 笔记本一接上HDMI转VGA转换器就黑屏,无法操作连接显示器
  8. apache commons-beanutils中BeanUtils和PropertyUtils区别
  9. WPF下CefSharp的使用
  10. syncnavigator关于win10、win8系统无法注册机进行激活的问题
  11. 偏差、方差、标准差、协方差
  12. 基于JAVA点餐系统的开题报告_开题报告-餐厅点餐系统的设计与实现.doc
  13. html5在线裁剪,HTML5 本地裁剪图片并上传至服务器(老梗)
  14. 测绘技能大赛-无人机航测虚拟仿真(内业部分)
  15. Matterport3D:室内环境RGB-D数据的深度学习
  16. 数据分析[1.1]--拆解方法总结
  17. python利用re正则表达式提取数据
  18. CAN通讯方式--秉火STM32学习笔记
  19. ckeditor 使用说明,手把手,详细步骤: ckeditor-5 online-builder,持续更新中~~
  20. 这是一个个人的“云图库”

热门文章

  1. Nagios监控软件源码安装
  2. 利用JAVA画一颗小心心
  3. 虚拟化——初始化系统配置
  4. 短信发送平台-阿里大于
  5. 美元兑人民币今天涨156个基点达到6.4044,人民币是否会持续贬值???
  6. [Swift]LeetCode825. 适龄的朋友 | Friends Of Appropriate Ages
  7. 【LeetCode】825. Friends Of Appropriate Ages 解题报告(Python)
  8. ElementUI分页与增删改合并
  9. 在KEIL中生成bin文件的方法
  10. 解决flask框架本地代码已经刷新,但是端口内容不变的问题