BUAAOO第二单元代码分析
第一次作业
设计思路与感想
第一次作业是要求有捎带的电梯实现, 第一次作业是花费的时间比较长的一次,花费了很多的时间去思考架构的问题.起初是想要搞三个线程的:输入线程,调度器线程和电梯线程,想要搞一个连锁的生产消费模型,但是在调度器线程和电梯线程在交互的时候出现了一些问题.
- 对run方法操作最小化的思考,
- 对于输入线程和调度器线程来说就是比较简单的,对于电梯线程我考虑了要不要添加一些非最小化的操作,比如:电梯加入moveTo()方法.
- 这样的方法在while(true)里面是不合适的,完全可以通过每循环一次移动一楼
- 这个moveTo具有占用大量时间的问题,因为上楼就要有0.4s的消耗,上楼这段时间没有办法执行下一次循环来响应请求.
- 所以run方法中含有while(true)建议每次循环都做最少的事,由小组成一个大的
- 对于三个线程即:输入,调度器,电梯线程的思考
- 这块我起初是想实现三个线程但是操作上还是出现了问题,虽然构建了流水线来搞,但是电梯线程有一个上下楼的等待时间,这个对于调度起来说,给不给电梯捎带请求是很难的一点,这个时候就需要加入一个电梯的返回来实现,而我没有这么做.
- 我是直接将电梯线程join到了调度器线程里面,这个时候电梯内部没有了while(true), 等到电梯执行完了调度器再继续执行.
- 交了作业以后,我发现其实此时的电梯线程已经没有必要再做成一个线程了,它完全就是一个普通的对象了.于是在下一次作业,将三线程变成了两线程
- 本次作业采用了als算法,性能不是很好,还是用look性能好一些.
类图分析

- 类之间调用的复杂度比较高,还是有一定的改进空间
度量分析
| Method | ev(G) | iv(G) | v(G) |
|---|---|---|---|
| "Command.Command(boolean)" | 1 | 1 | 1 |
| "Command.addCommand(int)" | 1 | 3 | 3 |
| "Command.getCommand()" | 1 | 3 | 3 |
| "Dispatcher.Dispatcher(LinkedList,Elevator,Command,boolean)" | 1 | 1 | 1 |
| "Dispatcher.checkIfSomeBodyGetIn()" | 3 | 2 | 3 |
| "Dispatcher.checkIfSomeBodyGetOff()" | 3 | 2 | 3 |
| "Dispatcher.closeDoor()" | 1 | 2 | 2 |
| "Dispatcher.downFloor()" | 1 | 2 | 2 |
| "Dispatcher.getIn()" | 3 | 4 | 4 |
| "Dispatcher.getOff()" | 3 | 3 | 3 |
| "Dispatcher.isSameDir(PersonRequest)" | 3 | 4 | 5 |
| "Dispatcher.openDoor()" | 1 | 2 | 2 |
| "Dispatcher.run()" | $\color{red}{6}$ | $\color{red}{13}$ | $\color{red}{15}$ |
| "Dispatcher.setStop(boolean)" | 1 | 1 | 1 |
| "Dispatcher.upFloor()" | 1 | 2 | 2 |
| "Elevator.Elevator(LinkedList,Command,Integer,boolean)" | 1 | 1 | 1 |
| "Elevator.arrive()" | 1 | 1 | 1 |
| "Elevator.close()" | 1 | 1 | 1 |
| "Elevator.down()" | 1 | 2 | 2 |
| "Elevator.getFloorNumNow()" | 1 | 1 | 1 |
| "Elevator.getIrq()" | 1 | 1 | 1 |
| "Elevator.isRuning()" | 1 | 1 | 1 |
| "Elevator.open()" | 1 | 2 | 2 |
| "Elevator.run()" | 1 | 5 | 5 |
| "Elevator.setRuning(boolean)" | 1 | 1 | 1 |
| "Elevator.up()" | 1 | 2 | 2 |
有一个方法的复杂度比较高,其他的方法还好.这个run方法里面多次调用了elevator里面的方法,而且多次启动新线程,可能是导致复杂度上升的原因.
时序图

第二次作业
设计思路与感想
本次作业是多部电梯之间协同工作,且设计了容量问题,我是将上次的作业进行了优化,将上次作业中的调度器和电梯线程之间合并为了一个电梯线程,这样的话,多部电梯,就只用一个电梯类来刻画即可以达到目的,同时电梯内部的调度策略换为了LOOK,电梯间的调度策略是为每部电梯定义了一个函数:f(a,b,c,d,e,f);
- a表示电梯所在的楼层
- b表示电梯的运行状态上还是下
- c表示该请求所在的楼层
- d表示该请求要去往的楼层
- e表示电梯外已有的等待人数
- f表示电梯内已有的人数
- 函数返回一个值来衡量电梯的负载情况
主线程读到请求后,直接分配给f(a,b,c,d,e,f)值最小的电梯来运行.由于与上次的改动并不多,也就不会出现线程安全的问题,而且这样的调度策略在性能上也是比较好的一个动态调度方案.
类图

类图也比较简单,只有两个类,elevator类结合了上次作业的捎带功能,main方法加入了一个电梯之间的分发问题.
度量分析
本次作业中最大值是getfd()方法,这个方法就是上文中提到的为了调度所定义的f(a,b,c,d,e,f) ,可能在实现上还是有面向过程的思想,导致该方法循环复杂度极高.
时序图

第三次作业
设计思路与感想
- 本次作业是多部多类型电梯之间的调度.
- elevator基本没有更改,只是增加了一些配置内容,这里是直接使用了type和if判断,这与面向对象的设计思想有不符的地方,但是为了各种安全性问题,还是决定不进行大改了
- 因为上一次的类数过少,有些类它的内部可能干的事情太多了,于是又抽象出了两个调度器类,不过这次它不再是一个线程了,而只是一个管理者.同类型电梯之间的调度方案和第二次作业相同,抽象出了Dispacher类.不同类之间采用先拆分为直达请求的方法,然后为电梯分配,于是又有了个DispacherTop类.从上到下进行管理
- 这次被hack出了线程安全问题,但是最后还是没有找到问题在哪,因为我是尽量减少共享对象的设计方案,所以可能是在增加电梯时的管理层级出现了问题.
类图

- 可以看到出现了跨层之间的调度,这个是因为请求拆分以后进入一个队列需要为电梯调用,那么拆分后的两条请求,第一条执行完毕需要告诉顶层的调度器去继续执行.
度量分析

- 类的复杂度比较高,原因在于我没有把请求队列,等待队列这些部分抽象出来,来降低耦合度.其实可以抽象出等待队列,来避免跨层之间的调度,而是都与等待队列来交互,实现解耦.
时序图

SOLID设计原则分析
- Single Responsibility Principle:单一职责原则:一个类应该只有一个发生变化的原因
- 本次作业尽量做到单一职责原则,但是有些地方因为拆分为类比较复杂,于是选择了耦合.
- Open Closed Principle:开闭原则:一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭
- 在每次作业中都有重新设计类图的结构,所以类都是改变过的,显然没有遵循到开闭原则.
- Liskov Substitution Principle:里氏替换原则:所有引用基类的地方必须能透明地使用其子类的对象
- 没有使用继承,在第三次作业中使用了type,所以也没有遵循这个规定.
- Law of Demeter:迪米特法则:只与你的直接朋友交谈,不跟“陌生人”说话
- 没有遵循到这个设计原则,也正因为没有使用第三方来发送信息,所以导致耦合度较高
- Interface Segregation Principle:接口隔离原则:
1.客户端不应该依赖它不需要的接口。
2.类间的依赖关系应该建立在最小的接口上。- 未使用接口,同继承,增加了耦合度.
- Dependence Inversion Principle:依赖倒置原则:
1、上层模块不应该依赖底层模块,它们都应该依赖于抽象。
2、抽象不应该依赖于细节,细节应该依赖于抽象。- 第三次作业中,上层模块依赖了底层模块,违反了依赖倒置原则.且没有实现抽象增加了耦合度
BUAAOO第二单元代码分析的更多相关文章
- BUAAOO第一单元代码分析
1.HomeWork1 思路 一个主类用于字符串得操作, 一个Poly类用于对一个多项式进行抽象,用Arraylist来对term进行封装.内部含有求导方法,添加并合并同类项的方法,toString方 ...
- BUAAOO第二单元多线程电梯作业总结
第二单元多线程作业需要保证线程安全
- OO第二单元作业分析
前言 这一单元关于线程安全的作业结束了,在助教提供的接口的帮助以及老师提供的设计模型的指导下,这三次作业还是相对轻松地完成了,中间也没有出现什么bug,可能就是因为简单的逻辑不容易出错吧,可惜两次都由 ...
- BUAA-OO第二单元小结
一.设计策略 三次作业中,由于前两次作业都只有一部电梯,因此我的线程只有两个,一个等待队列输入进程,以及一个电梯运行进程.等待队列输入进程实现十分简单,只需要根据输入把request添加到等待队列即可 ...
- BUAAOO第二单元总结之电梯问题
---恢复内容开始--- Homework1 傻瓜电梯 程序架构 第一次题目非常简单,思考也非常简单,一部电梯傻瓜调度.将命令入公共的队列,电梯从公共队列中取命令即可,其中只需要使用ArrayBloc ...
- 【BUAA-OO】第二单元作业总结
第二单元作业总结 ——电梯恐惧症患者的极限自救 一. 第一次作业程序分析 1. 设计策略简略分析 线程:主线程.输入线程和电梯线程,另有一个持有请求队列的调度器,一个对输入进行处理的Req ...
- OO第二单元作业小结
前言 转眼已是第九周,第二单元的电梯系列作业已经结束,终于体验了一番多线程电梯之旅. 第一次作业是单电梯的傻瓜调度,虽然是第一次写多线程,但在课程PPT的指引下,写起来还是非常容易:第二次作业是单电梯 ...
- OO第二单元总结
这一单元作业是围绕电梯调度进行展开,并引进了多线程的概念.与第一次作业比较类似,作业难度也是逐渐推进,从最开始的单部电梯先来先服务(傻瓜式调度),到之后的单部电梯可稍带调度,到最后的多部电梯分楼层调度 ...
- OO_第二单元总结
第二次总结博客(电梯单元) 16071070 陈泽寅 2019.4.20 一:多线程实验初感 这个单元是多线程设计的实践单元,主要让我们运用多线程的原理与思想去完成一个模拟电梯运行的策略.从最开始的单 ...
随机推荐
- input number step
input number step <!DOCTYPE html> <html> <body> <h1>The input step attribute ...
- ffmpeg concat设置绝对路径
https://superuser.com/questions/718027/ffmpeg-concat-doesnt-work-with-absolute-path/1551017#1551017 ...
- 多种转弯角度的PBN旁切转弯图例分析
无论世界怎样变化,我们依然是有点阳光就灿烂.面对世界的未知,最好的状态是勇敢的去面对,努力的去生活. 今天我们继续来聊一下PBN旁切转弯. PBN转弯保护区的结构通常都与它们的转弯角度大小有关,转弯角 ...
- 修改vs模板抬头\Common7\IDE\ItemTemplates\CSharp\Code\2052\Class
//************************************************************************************************** ...
- 基于tcp的应用层消息边界如何定义
聊聊基于tcp的应用层消息边界如何定义 背景 2018年笔者有幸接触一个项目要用到长连接实现云端到设备端消息推送,所以借机了解过相关的内容,最终是通过rabbitmq+mqtt实现了相关功能,同时在心 ...
- 读取excel数据生成sql脚本
package com.interact.util; import jxl.Cell; import jxl.Sheet; import jxl.Workbook; import jxl.read.b ...
- Python中的sklearn--KFold与StratifiedKFold
KFold划分数据集的原理:根据n_split直接进行划分 StratifiedKFold划分数据集的原理:划分后的训练集和验证集中类别分布尽量和原数据集一样 #导入相关packages from s ...
- Android 7.0 TextView点击事件无效修复方案
public class PostTextView extends TextView { private Handler handler = new Handler(Looper.getMainLoo ...
- 01.从0实现一个JVM语言之架构总览
00.一个JVM语言的诞生过程 文章集合以及项目展望 源码github地址 这一篇将是架构总览, 将自顶向下地叙述自制编译器的要素; 文章目录 01.从0实现一个JVM语言之架构总览 架构总览目前完成 ...
- 大话Spark(7)-源码之Master主备切换
Master作为Spark Standalone模式中的核心,如果Master出现异常,则整个集群的运行情况和资源都无法进行管理,整个集群将处于无法工作的状态. Spark在设计的时候考虑到了这种情况 ...
