OO_JAVA_电梯运行模拟_单元总结

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

[TOC] 。。博客园不支持目录。。安全

整体遵循的设计思路

逻辑解耦

电梯与调度器解耦

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

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

从第二次做业开始,我创建了Stage类,负责保存楼层信息;多线程

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

调度器运行流程解耦

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

  1. 获取主请求,也就是分发指令的依据
  2. 根据主请求分发指令
  3. 推送指令和须要进入电梯人员到与电梯交互的数据单元
  4. 检测电梯返还人员,从本调度器处理队列中删除,第三次添加了:若是须要转乘,则从新插入顶层调度器

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

返回目录函数

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

类方法复杂度表

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

可见的是,个人方法复杂度都很低,由于类也比较少,没什么衡量价值工具

返回目录spa

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

第二次电梯运做原理图

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<Integer| Person>)" 1 1 1
"machine.elevator.Elevator.setStage(Stage)" 1 1 1
"machine.elevator.Elevator.setToBeExec(List<Instruction>)" 1 1 1
"machine.elevator.Elevator.setToBeRemoved(Queue<Person>)" 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<Person>)" 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<Integer, Person>)" 1 1 1
"machine.elevator.Elevator.setStage(Stage)" 1 1 1
"machine.elevator.Elevator.setToBeExec(List<Instruction>)" 1 1 1
"machine.elevator.Elevator.setToBeRemoved(Queue<Person>)" 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工程写得实在是太慢了,从周六晚写到周二早,第二次电梯第三次电梯都是这样,第一次也少不了多少,,仍是小将想指挥全军,能力不足啊。

相关文章
相关标签/搜索