如下是某場的一道面試題(大概):php
一、一個停車場,車輛入場時,攝像頭記錄下車輛信息
二、屏幕上顯示所接收的車輛的信息狀況(車牌號)以及各層車位的車位餘量
三、停車場一共四層車位,其中的三層都爲普通車位,還有一層爲特殊車位(體如今停車計費價格上面的不一樣)css
看到第一個條件的時候,我大概知道了這道題考察的應該是面向對象相關的,三個條件看完後以及基本確認了。html
說到這裏,簡單地說一下面向對象,至於什麼是面向對象我這裏就很少說了,每一個人也都有本身不一樣的理解,包括它的三要素(封裝、繼承、多態)。前端
簡單地說一下爲何咱們要面向對象,爲何要使用面向對象?說一下個人理解
先拋開面向對象,首先計算機的 程序執行 無非就是 順序、判斷、循環 咱們如今全部用到的語言包括c、java、php... 沒有其它的, 如js中的 if...else, switch...case...就是判斷,for,while就是循環,也包括一些遍歷、遞歸也都是基於這三種方式!咱們天天所產出的代碼,全部的這些都是經過順序、判斷和循環這三個方式都能輕鬆搞定,沒有第四種方式,爲何呢?由於咱們經過這三種方式來解決就實現了一個結構化的問題,也就是咱們經過這三個就能知足全部的需求,也就不須要第四個了這樣的化對咱們的程序就已經結構化了,對於編譯器也能很高效的執行、解析這些東西, 外插一嘴,goto語句其實就是遊離在這三個以外,會致使程序、邏輯的混亂,不多有用基本被淘汰了,不能說他由於效率低,它的效率可能會很高,可是由於脫離告終構化,因此至少在業務代碼上咱們極少使用它。
說到這裏,也就是程勳執行咱們都簡化成 這個結構,而面向對象也讓咱們的數據也簡化了即結構化(這句話也不是我說的,而是ruby語言的做者),書裏說了,面向對象是爲了模擬、表示事件得萬物,好比人、鳥類、到具體服務員類,有具體行爲的類。其實js裏面向對象意義根本不拘泥於此,書上的只是爲了讓咱們好入門好學習而已,它的意義是將零散的數據進行結構化。計算機有個毛病,結構化的程序對於它來講是最簡單的!
簡單解釋一下,咱們瀏覽器加載網頁加載的是什麼?是流,流是什麼呢?其實就是字符串,雖然咱們看到以後是html,css,js代碼,可是代碼不就是字符串嘛,那咱們字符串怎麼辦,瀏覽器拿到字符串首先就是dom節點的解析而後生成生成渲染樹(渲染樹與dom樹不一樣的地方在於,dom樹會把全部的dom節點都展現出來,渲染樹只會展現display非none的元素),都是一步步順序執行的。
相比來講,程序也是如此了,若是咱們的程序中充滿了散亂的數據,那咱們還怎麼按照結構化的要求去操做呢?好比說,經過人作一個對象,人有外貌,行爲,狀態(吃、傳、喝、高矮胖瘦)這麼多東西能夠集成在一個對象中來操做,可是若是沒有面向對象,這些特徵,行爲也就散亂了,一旦散亂了之後還怎麼管理,而且這只是一我的,就有這麼多東西,再來十個,一百個,再來只狗類呢?咱們的程序就成了人心渙散了,固然這些只是舉例子,具體業務還要拿來具體分析。因此面向對象不只符合計算機所喜好的結構化,還能讓咱們管理起來,維護起來,都符合結構化。
再引用雙越老師的一句話:編程就應該簡單&抽象。
有一篇小說裏面有一段話我以爲還蠻有意思的,早期的人們之因此沒有設計出來計算機,就是由於他們想的不夠簡單,而不是不夠複雜,其實計算機很簡單,不就是0和1嗎。
全部說咱們編程,設計時候要作到 結構化,簡單+抽象,抽象完以後才能簡單,簡單的前提是咱們應該抽象好,我認爲這就是咱們爲何要面向對象最主要的緣由,咱們之因此面向對象編程就是由於它能夠抽象,能夠擴展。而不是面向具體,可能這些話對於初學前端的來講很差理解,可是隨着你工做時間的提高,相信很快就會理解的。java
**回到面試題,咱們來分析** 這個面試題,若是咱們沒有面向對象,面向抽象的概念, 那咱們應該很快就能拿起鍵盤了,一個停車場,三個普通車位,一個豪華車位,一個攝像頭,一個大屏幕顯示器,各類各樣的車,可能咱們很快就能作完,‘設計完’,畢竟面向具體是真的很簡單,要求什麼我就作什麼。。。 不過說回來,若是面試官再讓你減一個車位或者增長兩個豪華車位,加兩個攝像頭?若是按照咱們以前的來寫,簡單。。。改一下不就好了,加一個豪華車位,加兩個攝像頭。。。其實到這裏想必已經涼涼了。 下面咱們來使用面向對象 類圖這裏就再也不畫了 首先面試題中所提到的咱們均可以當作類,好比停車場是一個類吧,它裏面的車位是一個類吧,攝像頭,屏幕。。。咱們均可以看作是類 停車場,有層位,有攝像頭,屏幕,因此咱們先來建立一個停車場,這一類 class Park { constructor () { } } 停車場有層位,層位裏面有若干車位 class Floor { constructor (num, places) { this.num = num this.places = places } } 車位也歸爲一類,車位有本身的狀態,有車,無車 class Place { constructor () { this.empty = true } } 車位分爲普通車位,豪華車位,可是不管是普通仍是豪華,他們也都有本身的狀態,有車,無車,因此咱們直接讓這兩個類繼承車位類 普通車位 class NormalPlace extends Place{ constructor () { super() } } 豪華車位 class SpecialPlace extends Place{ constructor () { super() } } 攝像頭 class Camera { constructor () { } } 電腦,能夠記錄全部車的數據 class Computer { constructor () { this.symbols = {} } } // 屏幕 class Screen { } 這樣一看咱們全部類都建立完了,差的是來分析他們的行爲,狀態,聯繫,這裏再也不多作分析。只舉一個簡單的例子,而後上完整代碼 停車場, 有層 攝像圖 屏幕,有出入車時所發生的行爲 class Park { constructor (floors) { this.floors = floors this.camera = new Camera() this.screen = new Screen() } in (car) { } out (car) { } } 我本身寫了一個簡單的demo,固然也沒有考慮得特別細緻 ***完整代碼***
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> body,html{ height: 100%; } ul,li { list-style: none; } #inform { text-align: center; color: #9f9f9f; font-size: 18px; } #inform span { color: #ff4a3d; } #earch { text-align: center; font-size: 20px; color: #2963ff; } </style> </head> <body> <ul id="inform"> <li>第一層車位數量100,空餘車位數量 <span data-num=1>100</span></li> <li>第二層車位數量100,空餘車位數量 <span data-num=2>100</span></li> <li>第三層車位數量100,空餘車位數量 <span data-num=3>100</span></li> <li>第四層車位數量 20,空餘車位數量 <span data-num=4> 20</span></li> </ul> <p style="text-align: center; color: #5eb4ff">收入 <span id="price">0</span> 元</p> <ul id="earch"> <li>統計</li> </ul> <script> let priced = document.getElementById('price') let earch = document.getElementById('earch') class Camera { constructor () { this.computer = new Computer() } record (car, place, floor) { this.computer.show(car) return { num: car.num, symbol: car.symbol, inTime: new Date(), place, floor } } } class Computer { constructor () { this.symbols = {} } show (car) { console.log(`車牌號爲${car.num}的${car.symbol}駛入`) if (this.symbols[car.symbol] !== undefined) { this.symbols[car.symbol] = this.symbols[car.symbol] + 1 document.getElementById(car.symbol).innerText = this.symbols[car.symbol] } else { this.symbols[car.symbol] = 0 earch.innerHTML = earch.innerHTML + `<li>${car.symbol} <span id="${car.symbol}">${0}</span> 輛<li>` } } } class Screen { reload (f, t) { let dom = Array.prototype.slice.apply(document.querySelectorAll('#inform span')) if (t === '1') { dom.map(el => { if (el.dataset.num === f + 1 + '') { el.innerText = --el.innerText } }) } else { dom.map(el => { if (el.dataset.num === f + 1 + '') { el.innerText = ++el.innerText } }) } } } class Park { constructor (floors) { this.floors = floors this.camera = new Camera() this.screen = new Screen() this.carList = {} this.fullFloor = [] this.wait = [] } in (car) { let canChoice = [] let floors = this.floors floors.map((el, index) => { if (el.emptys > 0) { canChoice.push(index) } }) if (canChoice.length === 0) { if (Math.random() > 0.2) { console.warn('沒有找到車位,撤了') return 'back' } else { console.warn(`沒有找到車位,繼續等待`) this.in(car) return 'wait' } } let fi = canChoice[Math.floor(Math.random() * canChoice.length)] let canChoicePlaceIndex = [] let places = floors[fi].places places.map((el, index) => { if (el.empty) { canChoicePlaceIndex.push(index) } }) let pi = Math.floor(Math.random() * canChoicePlaceIndex.length) this.carList[car.num] = this.camera.record(car, pi, fi) places[pi].in(floors[fi]) this.screen.reload(fi, '1') let outs = Math.ceil(Math.random() * 100000 + 5000) setTimeout(() => { this.out(car) }, outs) } out (car) { let place = this.floors[this.carList[car.num].floor].places[this.carList[car.num].place] place.out(this.floors[this.carList[car.num].floor]) let price = (new Date() - this.carList[car.num].inTime)/1000 * place.price this.screen.reload(this.carList[car.num].floor) console.log(`車牌號爲${car.num}駛出, 收費 ${price} 元`) priced.innerText = (Number(priced.innerText) + Number(price)).toFixed(2) delete this.carList[car.num] } } class Floor { constructor (num, places) { this.num = num this.places = places this.emptys = places.length } inP () { this.emptys-- } outP () { this.emptys++ } } class Place { constructor () { this.empty = true } in (floor) { this.empty = false floor.inP() } out (floor) { this.empty = true floor.outP() } } class NormalPlace extends Place{ constructor () { super() this.color = 'blue' this.price = 10 } } class SpecialPlace extends Place{ constructor () { super() this.color = 'yellow' this.price = 60 } } class Car { constructor (type, num, symbol) { this.permit = type === '1' this.num = num this.symbol = symbol } } // 如下部分所有爲配合實現,請勿浪費時間觀看 let Floors = [] for (let i = 0; i < 3; i++) { let places = [] for (let j = 0; j < 100; j++) { places.push(new NormalPlace()) } Floors.push(new Floor(i + 1, places)) } let specialPlace = [] for (let i = 0; i < 20; i++) { specialPlace.push(new SpecialPlace()) } Floors.push(new Floor(4, specialPlace)) let park = new Park(Floors) var str = [] for(var i = 65; i < 91; i++){ str.push(String.fromCharCode(i)) } let test = { s: ['京', '冀', '黑', '蒙', '陝', '戶', '津', '贛', '浣', '深', '藏', '疆' ], n: str, u: ['奔馳', '勞斯萊斯', '路虎', '大衆', '保時泰', '保時捷', '蘭博基尼', 'QQ', '豐田', '本田', '吉利', '寶馬', '邁巴赫', '公交車', '火車', '坦克', '紅旗', '捷豹', '法拉利', '賓利'] } let enterTime = 100 setInterval( () => { let number = test.s[Math.ceil(Math.random() * test.s.length) - 1] + test.n[Math.ceil(Math.random() * test.n.length) - 1] + Math.floor(Math.random() * 100000) let na = test.u[Math.ceil(Math.random() * test.u.length) - 1] let car = new Car('1', number, na) park.in(car) enterTime = Math.floor(Math.random() * 50) }, enterTime) </script> </body> </html>
代碼能夠直接粘貼到html裏,直接運行打開,你們只要看各個類之間的聯繫就能夠,具體到行爲的邏輯代碼只是怎麼簡單想怎麼寫就怎麼寫的,固然也有沒考慮全面的,好比各個車位的價格應該也是動態的,爲了趕時間,好多東西我都直接定死了。
抽象好了以後,這樣不管是增長減小變動價錢咱們均可以靈活地處理,每一個類最基礎的行爲和方法幾乎是不變得,咱們只須要變容易變得抽象起來,封裝起來。以後, 就變得‘簡單’面試
歡迎一塊兒探討,你們共同進步!編程
做者:易企秀——Yxaw