面向对象课程总结博客
一、UML单元设计架构
本单元的任务集中在给定UML图,分析UML图结构,并给出相应的查询结果。第一次作业进行类图的相关查询,第二次作业增加了状态图和时序图的查询。
1、第一次UML设计架构
在分析由mdj文件dump出的信息之后,我们可以将UML类图的结构归纳为:
- UMLClass
- UMLOperation
- UMLParameter
- UMLAttribute
- UMLInterfaceRealization
- UMLGenerealization
- UMLAssociation
- UMLAssociationEnd
- UMLOperation
- UMLInterface
- UMLGenerealization
- UMLOperation
- UMLAssociation
- UMLAssociationEnd
由于dump出的UML类具有清晰的结构特征,我第一反应就是采用语法分析(递归下降子程序法,编译课设中所学)去解析给定的UMLElements,并建立相应的数据结构(HashMap,HashSet),为所要实现的接口准备数据。以下是准备的数据:
private UmlElement[] umlEles;
private HashMap<String, String> id2class; //ID-->类名
private HashMap<String, String> class2id; //类名-->ID
private HashMap<String, String> id2interface; //ID-->接口名
private HashMap<String, Integer> classNameAndItsCnt; //类名及其数量
private HashMap<String, ClassMethod> classname2Method; //类ID及其各种类方法
private HashMap<String, ClassAttr> class2Attr; //类ID及其各种属性
private HashMap<String, String> classGer; //类ID继承关系,key为子,value为父
private HashMap<String, HashSet<String>> classAsso; //类ID及其直接相关类ID
private HashMap<String, Integer> classAssoCnt; //类ID直接关联数量
private HashMap<String, HashSet<String>> interGer; //接口ID继承关系,接口支持多继承
private HashMap<String, HashSet<String>> classInterface; //类ID实现的接口ID
private int classCnt = 0;
private int idx = 0;
private int length;
由此,通过两遍扫描,第一遍存储class、interface的name和id对应表;第二遍存储联系、继承等关系。相应的接口算法利用存储的数据很容易实现。
尤其注意的是,class和interface均可能出现重名,若查询的不是重名的class或interface,而所建立的表是基于name而非id,则会出现很多关系遗漏。
2、第二次UML设计架构
第二次作业在第一次作业的基础上增加了类属性重名、循环继承、重复实现的检查,以及状态图和时序图的查询。
第二次作业新增的UML元素及其结构如下:
- UMLStateMachine
- UMLRegion
- UMLPeseudoState
- UMLState
- UMLTransition
- UMLEvent
- UMLFinalState
- UMLRegion
- UMLInteraction
- UMLLifeline
- UMLMessage
- UMLAttribute
同第一次作业类似,状态图以及时序图dump出的UMLElements同样具有很强的层次结构。于是,对状态图和时序图的解析,我同样采取了类似语法分析的处理,即把整个时序图、状态图的UMLElements当作一块来处理。为了避免代码块的臃肿,我将本次作业要实现的类继承了上次作业已经实现的类(实现了一部分代码)。对接口实现的处理,我与第一次作业一样,同样是扫描准备数据+利用数据实现。以下是我第二次作业新准备的数据结构:
private HashMap<String, Integer> machCnt; //状态机模型名称及其个数
private HashMap<String, Integer> actCnt; //时序图名称及其个数
private HashMap<String, StateMachine> machState; //状态机模型名称name及其内容
private HashMap<String, Interaction> name2Interact; //时序图模型名称name及其内容
二、单元结构设计
(1)第一单元 : 表达式求导
由于之前基本上未接触过面向对象式编程,在第一次作业时,我只创建了一个主类,对输入的处理,读取字符串,以及最后的求导和化简,采用两条arraylist存储系数和指数基本上完全采取过程化编程。
第二次作业,增加了三角函数项sin和cos,我创建了factor类,其属性包含每个因子的系数,x、sin(x)、cos(x)的指数。相比第一次作业,有了类的初步概念。
第三次作业,增加了嵌套后,多项式也来越复杂,不能像第二次作业那样简单的处理因子,于是我创建了更多的类来管理各式各样的形式的因子,并使这些类实现同一个求导接口来集中管理这些类,通过多态实现对不同形式因子的求导。
相比第一次作业只有一个Main主类,到第二次作业有factor和Main两个主类,最后针对不同形式的因子创建不同的类,并通过接口统一管理,我渐渐有了面向对象的概念。
(2)第二单元 : 多线程电梯
抛弃轮询策略,学会使用synchronized,wait,notifyall等关键字协调线程,避免线程之间的冲突,进一步理解并实现生产者-消费者模型。
除主请求外,有输入线程、调度器线程、电梯线程,一共三个线程。
输入线程和调度器之间共享请求队列。请求队列单独设立一个类,类中所有对请求队列进行操作和查询的方法均用synchronized修饰。调度器线程在判断请求对列为空时,进入wait状态;输入线程得到一个新请求时notify唤醒调度器。(这两个线程共享一把锁lock用于wait和notify)
调度器和这一部电梯共享一个请求队列,这个请求队列由电梯管理维护,代表由调度器分配给该电梯的请求。电梯在判断自己的请求队列和正搭载的人为空时进入wait状态,调度器在分配给这部电梯任务时,即将主请求队列中的请求分配给该部电梯的请求队列时,notify唤醒被分配任务且处于wait状态的电梯。由于这阶段仅有一部电梯,主请求队列中的请求全部直接交付给这一部电梯,即调度器只是将主请求队列中的请求直接搬运到这唯一一部电梯本身的请求队列中。
由于电梯维护自身的请求队列和正在搭载的乘客队列,具体的捎带策略由电梯本身来实现。
(3)第三单元:JML规格实现
这一单元,我们学习了JML规格,依照正确的JML规格实现的代码,能保证其实现的正确性。
在这一单元,我们所要实现的是一个地铁查询系统。地铁的拓扑图会随指令重构,同时也会进行大量的查询指令。第一次作业时,我所有的查询指令都是基于给定的图进行查询,由于图重构指令很少,而图查询指令很多,造成了cpu超时。在第二次,第三次作业实现时,我都是在图重构时,将所有节点之间的信息全部准备好,查询指令只需在准备好的数据中进行索引即可,此举大大减少了cpu所消耗的时间。
三、测试风格演进
第一单元,手动构造测试集,尝试覆盖所有的情况和分支。
第二单元,由于模拟了实时输入,因此使用了讨论区提供的魔改包,编写数据生成器,生成随机数据模拟输入。
第三单元,使用Junit,实现白盒测试和黑盒测试。对于新增的需求添加Junit测试内容,对于程序整体,编写随机数据生成器,将数据提供给输入并记录输出。
第四单元,自己编写mdj文件并添加查询内容,通过黑盒测试检查。
四、课程收获
本学期oo课程的学习,我的收获是循序渐进,逐步积累的。
- 第一单元
- 第二单元
- java的多线程机制
- sleep,wait,notify,synchronized关键字的理解与使用
- 同步/互斥访问机制
- 第三单元
- 规格语言:JML
- JML语法结构
- 由JML进行代码实现
- Junit进行“白盒测试”
- 第四单元
- java的结构语言:UML
- UML的基本类图信息
- UML的顺序图、状态图
五、一些建议
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。