1. 程式人生 > >【學習心得】傳說中的7K面試題——交通燈問題

【學習心得】傳說中的7K面試題——交通燈問題

 

---------------------- android培訓java培訓、期待與您交流! ----------------------


               Java是面向類的設計方式是,在用java解決交通燈問題時要充分分析交通燈中的各個類。特別要注意張老師在《精通面向類的分析和設計之祕訣》時說的幾個典型面向類的例子,記住一句話——誰擁有資料,誰就對外提供操作這些資料的方法。但是張老師說“售貨員統計收穫小票的金額”是小票自己在算(小票自己能算?),我是這樣理解的,小票擁有資料,所以把小票設計成一個類,該類中包含統計金額的功能(不知道對不對);其他的幾個例子還是可以理解。回到交通燈的問題,交通燈的燈就不總結了,張老師的圖示法很有效,一看就能明白;然後看整個問題包含的可能類:燈,車,路。燈肯定是有的,因為燈要產生控制車流動的訊號量;車,聽了張老師的分析,我們知道,車只不過是一個表示車輛已經通過的訊號,沒有必要設計成類,設計了更麻煩;還有路,按照誰擁有資料(這裡是車),誰就對外提供操作這些資料的方法,所以路要是一個類,用來操作車輛。我覺得整個過程就是燈類產生訊號,傳遞給路類,路類根據燈訊號操作車輛。說起來容易做起來難啊,如果不聽張老師的講解,這點知識我也總結不出來。

燈類包括燈類和燈控制類(可以只用一個類來完成這兩個類的功能,但是把燈抽取出來在結構上更清晰),燈控制類是初始化燈的紅綠併產生定時器控制燈由綠變紅,張老師在講解這點時還提到一個技巧,就是當前將要變紅的下一個燈呼叫blackOut()方法,該方法返回的是下一個將要變綠地燈,這樣燈系統就可迴圈了(實際上,燈只在四個燈之間迴圈變化,這個設計極大的簡化了設計過程)。

          接下來,我們詳細分析燈的兩個類——Lamp和LampController。Lamp用列舉來定義,因為燈是固定的,不需要變化(單例思想)。private Lamp(String opposite,String next,boolean lighted)方法在設計時根據需要傳遞三個引數(分別對應當前燈的反方向的燈、當前燈的下一個燈,當前燈是否亮)。所以我們在以後的設計中可以參考這種思想——方法涉及到多個數據時,直接把資料設計成引數(一句廢話),我覺得張老師設計的巧妙之處在於他把燈類簡化(含有實際邏輯的就只有四個燈),而且把四個燈在定義列舉時就關聯起來了。其他沒有邏輯的燈在定義式就直接把相應的關聯引數Null了,還有4條一直可以通過的燈常亮。這裡還要說一點是Lamp.valueOf(opposite)方法,由於Lamp是列舉,在定義式Lamp(String opposite,String next,boolean lighted)的關聯引數是String型別的,所以我們在呼叫String opposite對應的列舉時要用valueOf(String)來獲得String對應的列舉。Lamp裡定義的light()和blackOut()方法還是好理解的,注意返回值,一個是void一個是Lamp。再來看燈控制類,其實燈控制類核心部分是執行緒池和定時器而已,newScheduledThreadPool(int corePoolSize)是個靜態方法,用來建立一個執行緒池,它可安排在給定延遲後執行命令或者定期地執行,返回的是一個ScheduledExecutorService類。然後呼叫scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)方法作為執行定時器。
    接下來我們再來看路類:路類是隨機產生“車輛”,“車輛”產生後放入ArrayList<String>中(看成可變陣列即可);隨機產生“車輛”,張老師的辦法是讓執行緒控制產生 “車輛”,產生一個“車輛”後,等待隨機秒,然後再產生“車輛”。每條路都有自己的控制執行緒,相關的執行緒池查閱API文件就知道了。要注意的是,張老師在execute()方法中使用的是匿名內部類,這個匿名內部類啟動一個執行緒,被啟動的執行緒是執行緒池pool提供的。路類還有需要完成的一個功能是判斷燈的訊號,然後將自己的“車輛”通過紅綠燈。這裡用到的是定時器,和前面介紹的等地定時器一樣,理解了前面的這裡也不難理解。
  最好發點小感慨,之前編寫的小程式都是一個類就能搞定,很少涉及到什麼多個類啊包啊啥的,這是第一次接觸系統的軟體開發。理解是理解的差不多了,但是整個自己完全寫出來估計還不行,加油吧.