电梯运行模拟——三次作业总结

总体遵循的设计思路

逻辑解耦

电梯与调度器解耦

在我的三次电梯作业里,追求的目标都是让电梯运行与调度器分离,电梯只负责按照指令运行,目前的最终版本中,指令有UP、DOWN、OPEN、CLOSE、STILL、STOP六条。

楼层信息的存储和变更与电梯、调度器解耦

从第二次作业开始,我建立了Stage类,负责保存楼层信息;

建立了Instruction类,负责描述电梯运行的指令以及对应的Stage的变化,Instruction类中有一个枚举类型表示指令类型,一个IntFunction类型函数表示楼层索引的变化。

调度器运行流程解耦

从第二次到第三次,我的调度器的逻辑部分都是解耦成如下4个部分:

获取主请求,也就是分发指令的依据

根据主请求分发指令

推送指令和需要进入电梯人员到与电梯交互的数据单元

检测电梯返还人员,从本调度器处理队列中删除,第三次添加了:如果需要转乘,则重新插入顶层调度器

这是一个轮询机制,顺序循环并分发指令,控制电梯。

第一次电梯,蠢笨串行先到先得电梯

类方法复杂度表

Method

ev(G)

iv(G)

v(G)

"Main.main(String[])"

1

1

1

"elevator.Dispatcher.Dispatcher()"

1

1

1

"elevator.Dispatcher.getWaitingQueue()"

1

1

1

"elevator.Dispatcher.printQueue()"

1

1

1

"elevator.Dispatcher.run()"

1

3

4

"elevator.Elevator.Elevator(int|int|int)"

1

1

1

"elevator.Elevator.OutPersonThread.OutPersonThread(int|Vector)"

1

1

1

"elevator.Elevator.OutPersonThread.run()"

1

3

3

"elevator.Elevator.addPassenger(int|int)"

1

1

1

"elevator.Elevator.getStage()"

1

1

1

"elevator.Elevator.getStatus()"

1

1

1

"elevator.Elevator.moveDown()"

1

2

3

"elevator.Elevator.moveTo(int)"

1

5

5

"elevator.Elevator.moveUp()"

1

2

3

"elevator.Elevator.release()"

1

1

1

"elevator.ElevatorOutput.formatOutput(Format|int)"

2

2

4

"elevator.ElevatorOutput.formatOutput(Format|int|int)"

2

2

4

"elevator.Person.Person(int|int|int)"

1

1

1

"elevator.Person.getFrom()"

1

1

1

"elevator.Person.getId()"

1

1

1

"elevator.Person.getTo()"

1

1

1

"elevator.TransferPersonRequest.TransferPersonRequest(Dispatcher)"

1

1

1

"elevator.TransferPersonRequest.run()"

3

2

5

"util.MultiMap.MultiMap()"

1

1

1

"util.MultiMap.get(K)"

1

1

1

"util.MultiMap.put(K|V)"

1

1

2

"util.MultiMap.remove(K)"

1

1

1

"util.MultiMap.toString()"

1

1

1

可见的是,我的方法复杂度都很低,因为类也比较少,没什么衡量价值

第二次电梯,可捎带无限容量电梯

第二次电梯运作原理图

sequenceDiagram

main ->> Dispatcher : 启动计时器、电梯调度器,然后结束

transfer ->> Dispatcher : 传递人员请求;结束时发送Person.END

transfer ->> transfer : 输入流截止便关闭

Stage -->> Dispatcher : 拿到楼层信息,计算指令

Dispatcher ->> Elevator : 发送指令,如果是开门指令,则等待人员返还

Dispatcher ->> Stage : 在发送指令后变更楼层

Dispatcher ->> Elevator : 发送待上电梯人员

Elevator -->> Dispatcher : 返还待下电梯人员

Dispatcher ->>Dispatcher : 拿到END且处理队列为空时,发送指令关闭电梯,自己也退出轮询

从第二次电梯开始,我的电梯是按照如上的设计架构完成的,这是让我觉得比较舒服的架构设计,其设计方向是在于模拟,而不是为最优解设计的。

类方法复杂度表

Method

ev(G)

iv(G)

v(G)

"Main.main(String[])"

1

1

1

"machine.Dispatcher.Dispatcher()"

1

2

2

"machine.Dispatcher.exec(Instruction)"

1

7

7

"machine.Dispatcher.getNewInstruction()"

6

4

9

"machine.Dispatcher.getNewMajorRequest()"

8

4

11

"machine.Dispatcher.run()"

1

5

5

"machine.Dispatcher.updatePersonMap()"

1

3

3

"machine.elevator.Elevator.Elevator(ReentrantLock)"

1

1

1

"machine.elevator.Elevator.close()"

1

1

1

"machine.elevator.Elevator.move()"

1

1

1

"machine.elevator.Elevator.open()"

1

1

1

"machine.elevator.Elevator.run()"

2

5

8

"machine.elevator.Elevator.setOutsideQueue(MapVisitor)"

1

1

1

"machine.elevator.Elevator.setStage(Stage)"

1

1

1

"machine.elevator.Elevator.setToBeExec(List)"

1

1

1

"machine.elevator.Elevator.setToBeRemoved(Queue)"

1

1

1

"machine.elevator.ElevatorOutput.formatOutput(Format|int)"

2

2

5

"machine.elevator.ElevatorOutput.formatOutput(Format|int|int)"

2

2

4

"machine.elevator.Stage.Stage()"

1

1

1

"machine.elevator.Stage.Stage(int)"

1

1

2

"machine.elevator.Stage.apply(IntFunction)"

1

1

2

"machine.elevator.Stage.checkIndex(int)"

1

1

2

"machine.elevator.Stage.checkStage(int)"

3

1

3

"machine.elevator.Stage.getStage()"

1

1

1

"machine.input.Person.Person(int|int|int)"

1

1

2

"machine.input.Person.equals(Object)"

2

1

2

"machine.input.Person.getFrom()"

1

1

1

"machine.input.Person.getId()"

1

1

1

"machine.input.Person.getSide()"

1

1

1

"machine.input.Person.getStatus()"

1

1

1

"machine.input.Person.getTo()"

1

1

1

"machine.input.Person.transSide()"

1

1

2

"machine.input.TransferPersonRequest.TransferPersonRequest(Queue)"

1

1

1

"machine.input.TransferPersonRequest.run()"

3

2

4

"machine.input.TransferRequest.TransferRequest(PersonMap)"

1

1

1

"machine.input.TransferRequest.run()"

3

2

4

"machine.instr.Instruction.Instruction(Instr|IntFunction)"

1

1

1

"machine.instr.Instruction.getFunc()"

1

1

1

"machine.instr.Instruction.getInstr()"

1

1

1

"util.MultiMap.MultiMap()"

1

1

1

"util.MultiMap.get(K)"

1

1

1

"util.MultiMap.put(K|V)"

1

1

2

"util.MultiMap.removeByKey(K)"

1

1

1

"util.MultiMap.removeValue(K|V)"

1

2

2

"util.MultiMap.toString()"

1

1

1

"util.PersonMap.PersonMap()"

1

1

1

"util.PersonMap.getFromPerson(int|Status)"

2

2

2

"util.PersonMap.getToPerson(int|Status)"

2

2

2

"util.PersonMap.hasElement(Person)"

3

3

4

"util.PersonMap.isEmpty()"

5

4

7

"util.PersonMap.putPerson(Person)"

2

2

3

"util.PersonMap.removePerson(Person)"

2

4

4

"util.PersonMap.toEnd()"

2

2

2

"util.PersonMap.toString()"

1

1

1

可以看出加粗的三个方法复杂度较高,分别是获取主请求、根据主请求生成新命令、还有personMap的isEmpty方法。

获取主请求由于personMap的不合理,得在遍历时分别获取personMap的两个子map,即fromUp和fromDown两个map,所以复杂度很高。

根据主请求生成命令复杂度高跟上一个函数同理。

personMap的isEmpty方法就是因为personMap内部成员是4个map,对每一个都isEmpty然后与起来,复杂度就高了。

类复杂度表

Class

OCavg

WMC

"Main"

1.00

1

"machine.Dispatcher"

5.17

31

"machine.elevator.Elevator"

2.22

20

"machine.elevator.Elevator.Format"

n/a

0

"machine.elevator.Elevator.Status"

n/a

0

"machine.elevator.ElevatorOutput"

4.50

9

"machine.elevator.Stage"

1.67

10

"machine.input.Person"

1.38

11

"machine.input.Person.Side"

n/a

0

"machine.input.Person.Status"

n/a

0

"machine.input.TransferPersonRequest"

2.00

4

"machine.input.TransferRequest"

2.00

4

"machine.instr.InstrFac"

n/a

0

"machine.instr.InstrFac.Instr"

n/a

0

"machine.instr.Instruction"

1.00

3

"util.MultiMap"

1.33

8

"util.PersonMap"

2.44

22

可以看出,加粗的Dispatcher类和ElevatorOutput类复杂度较高,后者不说了,这个很难避免,前者复杂度高的原因是,目前大部分的逻辑处理部分在这一层,实现了轮询生成指令并分发,又有前述的两个方法加成,所以复杂度很高,当然,这个还与我的数据结构设计有一定的关系,personMap设计得很糟糕,如果改进数据结构并分离一些逻辑,想必复杂度会降下去的吧。

第三次电梯,可达楼层、运行速度和容量均不相同的多电梯

第三次电梯运作原理图

sequenceDiagram

main ->> Scheduler : 启动计时器、电梯调度器,然后结束

transfer ->> Scheduler : 传递人员请求

transfer ->> transfer : 输入流截止便关闭

Scheduler ->> Dispatcher : 启动三部电梯的调度器

Scheduler ->> Dispatcher : 发送人员请求

Dispatcher ->> Elevator : 启动电梯

Stage -->> Dispatcher : 拿到楼层信息,计算指令

Dispatcher ->> Elevator : 发送指令,如果是开门指令,则等待人员返还

Dispatcher ->> Stage : 在发送指令后变更楼层

Dispatcher ->> Elevator : 发送待上电梯人员

Elevator -->> Dispatcher : 返还待下电梯人员

Dispatcher -->> Scheduler : 返还需要转乘的人员请求

Scheduler ->> Dispatcher : 在电梯没有处理任务、scheduler没有处理任务且拿到END时,传递结束指令

这里实际上scheduler是给三个Dispatcher发送不同的人员请求但是为了说明的简易,只画了一个Dispatcher、Stage、Elevator组。

类方法复杂度表

Method

ev(G)

iv(G)

v(G)

"Main.main(String[])"

1

1

1

"machine.Scheduler.Scheduler()"

1

1

1

"machine.Scheduler.dispatchPerson()"

1

1

1

"machine.Scheduler.putPersonToElevator(Person)"

1

2

2

"machine.Scheduler.run()"

1

4

4

"machine.elevator.Dispatcher.Dispatcher(Stage,String,long,int,ReentrantLock)"

1

1

1

"machine.elevator.Dispatcher.exec(Instruction)"

1

5

5

"machine.elevator.Dispatcher.getNewInstruction()"

11

7

13

"machine.elevator.Dispatcher.getNewMajorRequest()"

1

3

5

"machine.elevator.Dispatcher.getPeopleMap()"

1

1

1

"machine.elevator.Dispatcher.run()"

1

5

5

"machine.elevator.Dispatcher.setToBePut(PeopleVector)"

1

1

1

"machine.elevator.Dispatcher.update()"

1

3

3

"machine.elevator.Elevator.Elevator(ReentrantLock,String,long,int)"

1

1

1

"machine.elevator.Elevator.close()"

1

1

1

"machine.elevator.Elevator.move()"

1

1

1

"machine.elevator.Elevator.open()"

1

1

1

"machine.elevator.Elevator.processInside()"

1

1

1

"machine.elevator.Elevator.processOutside()"

2

1

2

"machine.elevator.Elevator.run()"

2

5

8

"machine.elevator.Elevator.setOutsideQueue(MapVisitor)"

1

1

1

"machine.elevator.Elevator.setStage(Stage)"

1

1

1

"machine.elevator.Elevator.setToBeExec(List)"

1

1

1

"machine.elevator.Elevator.setToBeRemoved(Queue)"

1

1

1

"machine.elevator.Stage.Stage(int[])"

1

2

3

"machine.elevator.Stage.apply(IntFunction)"

1

2

2

"machine.elevator.Stage.checkIndex(int)"

1

1

2

"machine.elevator.Stage.couldStall()"

1

1

1

"machine.elevator.Stage.getStage()"

1

1

1

"machine.elevator.Stage.initStage(int)"

1

2

2

"machine.elevator.Stage.isReachable(int)"

1

1

1

"machine.elevator.Stage.isReachableByIndex(int)"

2

2

2

"machine.elevator.Stage.stageToIndex(int)"

3

1

4

"machine.elevator.Stage.toString()"

1

1

1

"machine.input.Person.Person(int,int,int)"

1

1

2

"machine.input.Person.equals(Object)"

2

1

2

"machine.input.Person.getDestination()"

2

1

2

"machine.input.Person.getFrom()"

1

1

1

"machine.input.Person.getId()"

1

1

1

"machine.input.Person.getSide()"

1

1

1

"machine.input.Person.getStatus()"

1

1

1

"machine.input.Person.getTo()"

1

1

1

"machine.input.Person.hashCode()"

1

1

1

"machine.input.Person.isOutside()"

1

1

1

"machine.input.Person.isUp()"

1

1

1

"machine.input.Person.needGetInside(int)"

1

1

2

"machine.input.Person.needGetOutside(Stage)"

3

2

3

"machine.input.Person.setMid(Stage,Stage)"

6

6

12

"machine.input.Person.toString()"

1

1

1

"machine.input.Person.transSide()"

1

1

2

"machine.input.Person.wantOne()"

3

4

7

"machine.input.TransferRequest.TransferRequest(PeopleVector,ReentrantLock)"

1

1

1

"machine.input.TransferRequest.run()"

3

3

5

"machine.instr.Instruction.Instruction(Type,IntFunction)"

1

1

1

"machine.instr.Instruction.getFunc()"

1

1

1

"machine.instr.Instruction.getType()"

1

1

1

"machine.output.Output.format(Format,int,String)"

2

2

5

"machine.output.Output.format(Format,int,int,String)"

2

2

4

"machine.util.PeopleMap.PeopleMap()"

1

2

2

"machine.util.PeopleMap.getCapcity()"

1

1

1

"machine.util.PeopleMap.getMap(Type)"

1

1

1

"machine.util.PeopleMap.getPerson(Type,int)"

1

1

1

"machine.util.PeopleMap.hasElement(Person)"

3

4

5

"machine.util.PeopleMap.isEmpty()"

1

2

2

"machine.util.PeopleMap.put(Type,Integer,Person)"

1

1

1

"machine.util.PeopleMap.putPerson(Person)"

3

2

5

"machine.util.PeopleMap.remove(Type,Integer,Person)"

1

1

1

"machine.util.PeopleMap.removePerson(Person)"

2

2

4

"machine.util.PeopleMap.toEnd()"

1

2

2

"machine.util.PeopleMap.toString()"

1

1

1

"machine.util.PeopleVector.PeopleVector()"

1

1

1

"machine.util.PeopleVector.putPerson(Person)"

1

2

2

"machine.util.PeopleVector.putPerson(Person,String)"

1

2

3

"machine.util.PeopleVector.toEnd()"

1

3

3

"util.MultiMap.MultiMap()"

1

1

1

"util.MultiMap.get(K)"

1

1

1

"util.MultiMap.isEmpty()"

1

1

1

"util.MultiMap.put(K,V)"

1

2

3

"util.MultiMap.removeByKey(K)"

1

1

1

"util.MultiMap.removeValue(K,V)"

1

2

2

"util.MultiMap.toString()"

1

1

1

"util.MultiMap.values()"

1

1

1

加粗的两个方法复杂度飘红了,还是蛮高的,一个是与之前一样的getNewMajorRequest方法,获取新的主请求,因为遍历对象,还有判断person的逻辑比较复杂,所以复杂度很高;

相比上回的改进是getNewInstruction方法复杂度已经没那么高了,因为将一部分逻辑引导到了person类中。

另一个是person类的setMid方法,其作用是设置person的中转目的地,因为拿取了两个stage对象并循环调用对象isReachable函数判断,所以复杂度较高,但并不是太高,只是刚刚超出。

类复杂度表

Class

OCavg

WMC

"Main"

1.00

1

"machine.Scheduler"

1.75

7

"machine.elevator.Dispatcher"

3.88

31

"machine.elevator.Elevator"

1.91

21

"machine.elevator.Elevator.Format"

n/a

0

"machine.elevator.Stage"

1.70

17

"machine.elevator.StageFac"

n/a

0

"machine.input.Person"

1.94

33

"machine.input.Person.Side"

n/a

0

"machine.input.Person.Status"

n/a

0

"machine.input.TransferRequest"

2.00

4

"machine.instr.Instr"

n/a

0

"machine.instr.Instr.Type"

n/a

0

"machine.instr.Instruction"

1.00

3

"machine.output.Output"

4.50

9

"machine.util.PeopleMap"

1.92

23

"machine.util.PeopleMap.Type"

n/a

0

"machine.util.PeopleVector"

1.50

6

"util.MultiMap"

1.38

11

Dispatcher类有点积重难返的意思,目前架构是这样了,当然,Dispatcher类完全可以把功能分散到其他类中,最后让他起组合搭桥的作用,就是把之前就描述的DIspatcher类的四个函数分离开来,变成新的类的处理逻辑,这样,应该可以显著减少他的复杂度把;

Person类WMC过高的原因是方法太多了,获取成员、判断进出、判断上哪一个电梯,这么多内容夹杂在一起,内部还有其他的工具函数,导致Person类复杂度很高,如果重构,可以把新的person类变成几个接口的组合,一个获取ID、FROM、TO的借口,一个判断进出相关工具函数的接口,或者单独开个类,处理人员是否需要进出和向上哪一个电梯的类,后者让person专职其责,也能降低复杂度,更好一点把。

Output类。。不用说了。

第三次电梯的所有类图景

作业bug分析

从架构上来说,我的程序在线程间的数据安全上,是没有问题的,所以bug主要出现在我某一个步骤没有完成,比如在写的过程中de出的一个bug,人从电梯里出来要从电梯内部的队列中删除,如果没有删除,导致一个人会出电梯数次,诸如此类,我犯得bug都是这样的错误,这些bug的主要原因是我的数据结构类设计的不够好,使用时头脑也不清晰,可变数据的坏处就在这,必须时时考虑数据该怎么变化迁移,或是添加或是删除。

除了上述说的,我还犯得的一个bug就是主请求选择bug,第三次电梯里,主请求选择没有考虑人满员的状况,选了outside的人,导致电梯日门,哭。/(ㄒoㄒ)/~~

多线程作业感想

我从表达式求导作业完成后,就一直比较在意这个问题,就是程序的架构,还有代码的复杂度,所以在电梯作业的编写中,我就一直做着我反复说的东西,就是分离分离再分离,将逻辑分散开来,当然,不能是随意地平行散列逻辑,应该是有所关联结构,按照层次化的方式构建起来的,不断将逻辑解耦,就是我在写程序中反复思考的内容,为此,我写这部分程序动辄删除或者重写,但是由于经验和能力的不足,依然没有设计出真正健壮、低耦合、复杂度低的架构,比如我的数据结构类,设计的还是让我很不满意,也增添了我其他使用该类的方法的复杂度,这是今后需要改进的,另外我的OO工程写得实在是太慢了,从周六晚写到周二早,第二次电梯第三次电梯都是这样,第一次也少不了多少,,还是小将想指挥全军,能力不足啊。

java模拟电梯面向对象_OO_JAVA_电梯运行模拟_单元总结相关推荐

  1. matlab 碗形状,付星020806-用matlab模拟小球撞碗的运行轨迹_理论力学

    用MATLAB 模拟小球撞碗的运行轨迹 仪21 付星020806 关键词:斜抛,小球撞碗,MATLAB模拟 参考书目:彭芳麟. 理论力学计算机模拟. 清华大学出版社. 2002 <力学与实践&g ...

  2. java面向对象电梯运行代码_面向对象编程总结——多线程电梯

    最近的三周面向对象的作业是电梯问题.主要是对多线程编程的一种训练.主要还是对生产者--消费者模型的使用的理解.作业分成了三个阶段,第一个阶段是FIFO调度策略的电梯.第二个阶段是可捎带的电梯设计,第三 ...

  3. 2022T电梯修理考试题库及模拟考试

    题库来源:安全生产模拟考试一点通公众号小程序 2022年T电梯修理复训题库系T电梯修理理论题库新版习题库!2022T电梯修理考试题库及模拟考试根据T电梯修理考前押题.T电梯修理复审题库通过安全生产模拟 ...

  4. c语言数据结构课程设计电梯,数据结构课程设计报告(模拟电梯).doc

    数据结构课程设计报告(模拟电梯) 山东理工大学计算机学院 课 程 设 计 (数据结构) 班 级姓 名学 号 指导教师 二〇一二年一月十日 课程设计任务书及成绩评定 课题名称电 梯 模 拟 Ⅰ.题目的目 ...

  5. 2022年T电梯修理操作证考试题模拟考试平台操作

    题库来源:安全生产模拟考试一点通公众号小程序 2022年T电梯修理全部考试题库系T电梯修理考试真题高频考题覆盖!2022年T电梯修理操作证考试题模拟考试平台操作依据T电梯修理考试大纲.T电梯修理试卷通 ...

  6. 2020T电梯修理模拟考试题及T电梯修理考试软件

    题库来源:安全生产模拟考试一点通公众号小程序 2020T电梯修理模拟考试题及T电梯修理考试软件,包含T电梯修理模拟考试题答案解析及T电梯修理考试软件练习.由安全生产模拟考试一点通公众号结合国家T电梯修 ...

  7. 2022T电梯修理考试题及在线模拟考试

    题库来源:安全生产模拟考试一点通公众号小程序 2022年T电梯修理复习题为T电梯修理考试题库模拟预测卷!2022T电梯修理考试题及在线模拟考试依据T电梯修理新考试大纲.T电梯修理复审题库随时根据安全生 ...

  8. 2020T电梯修理模拟考试及T电梯修理实操考试视频

    题库来源:安全生产模拟考试一点通公众号小程序 2020T电梯修理模拟考试及T电梯修理实操考试视频,包含T电梯修理模拟考试答案解析及T电梯修理实操考试视频练习.由安全生产模拟考试一点通公众号结合国家T电 ...

  9. 2022年T电梯修理题库及模拟考试

    题库来源:安全生产模拟考试一点通公众号小程序 2022年T电梯修理复习题是T电梯修理全部考试题库精选题库!2022年T电梯修理题库及模拟考试根据T电梯修理新版教材大纲编写.T电梯修理考试资料随时根据安 ...

最新文章

  1. tengine简单安装_Tengine介绍和安装
  2. 数据蒋堂 | 数据压缩手段
  3. android 自定义dialog 定时关闭,Android编程实现自定义Dialog的大小自动控制方法示例...
  4. android如何查看分区信息,android如何查看分区信息
  5. MyEclipse 常用设置和操作方法
  6. JavaMail发送简单邮件
  7. javascript冷门吗_分享几个html5冷门小知识
  8. sol - 0x60,61,62
  9. sarscape 将dem文件转化成stl_SARscape与SARProz软件中的重要缩写
  10. Java实现首字母大写、驼峰命名与、划线转换,校验null
  11. 判断浏览器是pc端还是移动端
  12. XEngine:深度学习模型推理优化
  13. 程序员有成立工会的理由吗?
  14. 1-3-JavaScript技术
  15. 光盘中删除数据如何恢复_电脑硬盘数据恢复教程,EasyRecovery软件讲解,恢复删除数据...
  16. redis cluster以及master-slave在windows下环境搭建
  17. 【特别版】考证与学习,结构与功能,之间的因果关系
  18. edius隐藏快捷键_Edius常用快捷键
  19. 考试计算机网络基础知识,事业单位考试计算机网络基础知识试题及答案
  20. phpyun怎么采集_phpyun采集

热门文章

  1. ESP32 学习日志(4)——OTA升级(1)-示例解析
  2. IBM AIX 安装说明
  3. 使用JS实现当当购物车结算页面
  4. 【无2022起重信号司索工(建筑特殊工种)考试题模拟考试题库及模拟考试
  5. Java虚拟机基本结构
  6. gun/linux more 搜索功能
  7. excel的数据通过pyecharts生成图表,插入ppt
  8. 【模拟集成电路】环路滤波器(LPF)设计
  9. 7-2 jmu-python-最佳身高 (10分) Python
  10. DES加密与解密代码