哈工大软件构造lab3实验心得(二)——实验思路

简述

承接上一篇博客,这篇是关于lab3的实验思路的,也就是我是如何一步一步思考,最终完成lab3的。话不多说,先上表。
在这里插入图片描述

总体任务

通读lab3实验手册之后,我将总体任务划分为如下几块:

  • PlanningEntry部分
  • Board部分
  • API部分
  • APP部分
  • 314Change

同时,手册建议/要求我们在某些地方使用一些设计模式,包括:

  • 在实现个性化特点时使用装饰器模式
  • 在实现状态转变时使用状态模式
  • 在设计API时使用外观模式
  • 使用工厂方法模式来创建具体的计划项对象
  • 使用迭代器模式为Board类增加迭代器
  • 设计API时使用策略模式,便于Client切换实际算法

依据我lab2实验心得给出的设计过程:

确立UML类图模型--->写好每个类的AF、RI与方法的spec(这一步需要花费很多时间,但是尤为重要)--->写Junit测试用例--->填代码

我将据此逐步展示我当时的思路。

确定UML类图模型

  • 原则

面向接口设计、以便于Client调用。这里的Client是广义的,不仅仅包括直面用户的客户端、也包括想要使用某个类的调用者,也视为Client。

  • 抽象出各个类

首先根据手册要求大致将需要的类划分一下

  1. 实验手册已经帮我们确定了一些类:Resource、Timeslot、Location、State、PlanningEntry、CommonPlanningEntry
  2. 因为我选择实现的是航班、高铁、活动
    所以自然地又抽象出3个类:FlightEntry、TrainEntry、ActivityEntry
  3. 实现Board功能的类
  4. 实现API功能的类
  5. 需要APP类将所有功能综合到一起,并提供给Client接口,以方便调用

接下来需要根据实际需求更近一步地细化抽象

  • 首先手册中要求我们对PlanningEntry进行泛型化处理,用R表示泛化资源类型,表现为PlanningEntry<R>
    关于泛型的使用详解,大家可以参考下面的这篇博客:
    这是来自csdn的一篇关于泛型用法的博客,总结地很全,可以点击查看

  • Resource类
    表示计划项所使用的资源,不同的计划项资源也不同,但都是Immutable的,所以我就将Resource设计成一个Interface,然后再设计三个具体实现类:Plane、Train、Material。这样便可满足要求了,而且可以直接用Resource来具体化PlanningEntry<R>中的R

  • Timeslot类
    因为三个计划项都会用到时间段,所以我们直接用一个Timeslot类来表示即可,并设计成Immutable

  • Location类
    与Timeslot类相似,直接用一个Location类来表示地点的概念即可,也设计成Immutable

  • PlanningEntry类
    根据面向接口设计原则,我首先将PlanningEntry设计成Interface;
    再根据本篇博客开头的那张表可见这三个计划项有部分共同点、也用部分特性,所以我将CommonPlanningEntry设计成具体计划项类的共同父类,并实现PlanningEnrty接口;

    public class CommonPlanningEntry<R> implements PlanningEntry<R>
    

    最后,设计3个具体计划项类,继承CommonPlanningEntry类:

    public class FlightEntry<R> extends CommonPlanningEntry<R>
    
    public class TrainEntry<R> extends CommonPlanningEntry<R>
    
    public class ActivityEntry<R> extends CommonPlanningEntry<R>
    
  • State类
    首先根据手册要求,转变状态要求使用状态设计模式,而我在lab3实验心得(一)这篇博客中已经给出了设计模式的学习途径。
    这是菜鸟教程中状态模式的说明,可点击查看
    这是状态模式UML图:主要意思就是将State设计成Interface,各种不同的具体状态类Implements这个State接口;
    Context是需要添加状态的类,把State添加进它的Field中,并提供Getter与Setter
    在这里插入图片描述
    据此,我设计出State接口与多个具体实现类
    举例ALLOCATED和BLOCKED以展示它们之间的关系:
    在这里插入图片描述

  • Board类
    一方面,3种计划项的Board展示的内容相差较大;另一方面,它们又有一些共同的Fields

//所有的计划项
protected final Set<PlanningEntry<Resource>> planningEntries;

所以,我将Board设计为一个抽象类,然后再设计3种具体计划项Board来extends
在这里插入图片描述

  • API
    实验手册要求使用策略模式
    在这里插入图片描述
    在这里,我只是将判断是否存在Location冲突用2种算法实现,所以我将PlanningEntryAPIs设计为抽象类,检查地点冲突设计abstract method

    public abstract boolean checkLocationConflict(List<PlanningEntry<Resource>> entries);
    

    然后在2种API中分别用不同算法实现:
    在这里插入图片描述
    在这里插入图片描述
    目前的API类关系图如下:
    在这里插入图片描述

  • APP
    APP其实就是将所有的功能都综合在一起,并统一提供对外接口。我将APP设计成Interface,再让3个具体APP类implements它。
    在这里插入图片描述

  • 进一步细化抽象类,并确定类之间的关系

    上一步中,我们已经大致将各个类抽象出来了,但是并不完整,还有些功能并不完备,所以在这一步中我们需要根据要求进一步补充类。

    • 如何实现计划项个性化特点

    • 计划项的资源数目、地点数目、时间段数目都不一样怎么处理?
      我直接在CommonPlanningEntry中使用list来存储这些信息了,简单粗暴。当然也有其他更好的存储方案,我就不逐一列举了。
    protected final List<Location> locations;
    protected final List<Timeslot> timeslots;
    protected List<R> resources;
    
    • 高铁计划项可以Block,如何实现?
      手册中给出了6种实现个性化特点的方案,我在这里选用的是CPR:
      在这里插入图片描述
      我设计了一个blockable接口,以及它的实现类blockableImpl,再让高铁计划项实现这一接口
      在这里插入图片描述
    • 活动计划项可以更改Location,如何实现?
      直接设计一个接口,再让活动计划项实现该接口即可public interface ChangeableLocation
    public class ActivityEntry<R> extends CommonPlanningEntry<R> implements ChangeableLocation
    
    • 3种具体的Board类该如何实现

      由于3种Board所展示的内容各部相同,且用GUI程序实现,我设计了3个界面类,都继承JFrame,专门处理GUI部分。然后3个Board委托界面类即可。
      以航班类为例:
      在这里插入图片描述
      在这里插入图片描述
      在自定义的界面类中,包含很多组件以及事件监听,这里也有一个小技巧:将初始化组件和所有的事件监听分别放在一个private方法中,在界面类的构造方法中调用。
      在这里插入图片描述
    • 3种具体的APP类该如何实现

      同Board的思想,也自定义界面类,然后APP类委托它进行可视化。
      至此,所有的类抽象完成!

写好每个类的AF、RI,方法的Spec

  • 确定每个类需要包含哪些方法

    这个就根据手册的要求来即可,自己灵活设计,能够满足需求即可
  • 这些方法需要传入哪些参数

    除去构造方法,类的method主要就2类:Observer和Mutator
    • observer:一般不需要参数
    • mutator:将新的Location、State等对象作为参数传入method,用来对相应的Filed进行修改即可
  • 写类的AF、RI;方法的Spec

    就按照王忠杰老师的ppt中示例代码的格式来写,这一步很花时间(我这一步好像用了2天时间),但是也尤为重要,不可忽视!

写好Junt测试

依据前面写好的AF、RI写黑盒测试(我们的课程只要求了黑盒测试)
然后可以利用EclEmma测试代码的覆盖度,当然黑盒测试的覆盖度可能不会太高。
关于此工具的使用,大家可以参考一位博主在博客园中发表的博客:
不仅能测试覆盖度,还能导出HTML报告呢!点击此处可查看

填代码

到了最后的填代码阶段了,这一阶段其实就是根据方法的Spec去完成各个方法;根据类的AF、RI写好所有类的Fields。这当然需要一定的java知识积累,同样,也建议采用需求驱动的原则去学习相应的知识点。

拿我写Timeslot基本类做例子,这个类表示时间段,需要2个Fileds,分别表示开始时间和结束时间。
我在此之前了解到的时间相关的类仅有Date、Calendar,但是上课时老师说过这2个类不安全,于是我便搜索java中Immutable的时间类,最终找到LocalDateTime类,这是java8新增的时间类,Immutable,使用起来很方便。

同时可以利用Java8在线API文档查询它的各种Method:
这便是Java8在线API文档,中文翻译版,可能有部分语句由于中文翻译的缘故读起来不太通畅

大家也可以去查阅英文原版文档:
这是官网的原版java8 API文档下载网站

总结

lab3任务太多了,根据前面的设计步骤来一步步做,我也做了5周。但是经过lab3的历练,我觉得不仅提升了自己的java编程能力;更重要的,是自主总结、自主根据需求去搜寻相关资料来学习、最终将自学的内容付诸于实践的独立学习能力。另外,lab3的最终完成,也表明前面的设计过程框架是可行的!

确立UML类图模型--->写好每个类的AF、RI与方法的spec(这一步需要花费很多时间,但是尤为重要)--->写Junit测试用例--->填代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值