一道面试题引起的思考

如下是某场的一道面试题(大概):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}&nbsp;<span id="${car.symbol}">${0}</span>&nbsp;辆<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
相关文章
相关标签/搜索