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工程寫得實在是太慢了,從週六晚寫到週二早,第二次電梯第三次電梯都是這樣,第一次也少不了多少,,仍是小將想指揮全軍,能力不足啊。

相關文章
相關標籤/搜索