一道面试题引发的思考

栏目: 后端 · 前端 · 发布时间: 5年前

内容简介:以下是某场的一道面试题(大概):1、一个停车场,车辆入场时,摄像头记录下车辆信息2、屏幕上显示所接收的车辆的信息情况(车牌号)以及各层车位的车位余量

以下是某场的一道面试题(大概):

1、一个停车场,车辆入场时,摄像头记录下车辆信息

2、屏幕上显示所接收的车辆的信息情况(车牌号)以及各层车位的车位余量

3、停车场一共四层车位,其中的三层都为普通车位,还有一层为特殊车位(体现在停车计费价格上面的不同)

看到第一个条件的时候,我大概知道了这道题考察的应该是面向对象相关的,三个条件看完后以及基本确认了。

说到这里,简单地说一下 面向对象 ,至于什么是面向对象我这里就不多说了,每个人也都有自己不同的理解,包括它的三要素(封装、继承、多态)。

简单地说一下为什么我们要面向对象,为什么要使用面向对象?说一下我的理解

先抛开面向对象,首先计算机的 程序执行 无非就是 顺序、判断、循环 我们现在所有用到的语言包括c、 java 、php... 没有其它的, 如js中的 if...else, switch...case...就是判断,for,while就是循环,也包括一些遍历、递归也都是基于这三种方式!我们每天所产出的代码,所有的这些都是通过顺序、判断和循环这三个方式都能轻松搞定,没有第四种方式,为什么呢?因为我们通过这三种方式来解决就实现了一个结构化的问题,也就是我们通过这三个就能满足所有的需求,也就不需要第四个了这样的化对我们的程序就已经结构化了,对于编译器也能很高效的执行、解析这些东西, 外插一嘴,goto语句其实就是游离在这三个之外,会导致程序、逻辑的混乱,很少有用基本被淘汰了,不能说他因为效率低,它的效率可能会很高,但是因为脱离了结构化,所以至少在业务代码上我们极少使用它。

说到这里,也就是程勋执行我们都简化成 这个结构,而面向对象也让我们的数据也简化了即结构化(这句话也不是我说的,而是 ruby 语言的作者),书里说了,面向对象是为了模拟、表示事件得万物,比如人、鸟类、到具体服务员类,有具体行为的类。其实js里面向对象意义根本不拘泥于此,书上的只是为了让我们好入门好学习而已,它的意义是将零散的数据进行结构化。 计算机有个毛病,结构化的程序对于它来说是最简单的

简单解释一下,我们浏览器加载网页加载的是什么?是流,流是什么呢?其实就是字符串,虽然我们看到之后是html,css,js代码,但是代码不就是字符串嘛,那我们字符串怎么办,浏览器拿到字符串首先就是dom节点的解析然后生成生成渲染树(渲染树与dom树不同的地方在于,dom树会把所有的dom节点都展示出来,渲染树只会展示display非none的元素),都是一步步顺序执行的。

相比来说,程序也是如此了,如果我们的程序中充满了散乱的数据,那我们还怎么按照结构化的要求去操作呢?比如说,通过人做一个对象,人有外貌,行为,状态(吃、传、喝、高矮胖瘦)这么多东西可以集成在一个对象中来操作,但是如果没有面向对象,这些特征,行为也就散乱了,一旦散乱了以后还怎么管理,并且这只是一个人,就有这么多东西,再来十个,一百个,再来只狗类呢?我们的程序就成了一盘散沙了,当然这些只是举例子,具体业务还要拿来具体分析。 所以面向对象不仅符合计算机所喜爱的结构化,还能让我们管理起来,维护起来,都符合结构化。

再引用双越老师的一句话: 编程就应该简单&抽象

有一篇小说里面有一段话我觉得还蛮有意思的,早期的人们之所以没有设计出来计算机,就是因为他们想的不够简单,而不是不够复杂,其实计算机很简单,不就是0和1吗。

所有说我们编程,设计时候要做到 结构化,简单+抽象, 抽象完之后才能简单,简单的前提是我们应该抽象好 ,我认为这就是我们为什么要面向对象最主要的原因,我们之所以面向对象编程就是因为它可以抽象,可以扩展。而不是面向具体,可能这些话对于初学前端的来说不好理解,但是随着你工作时间的提升,相信很快就会理解的。

**回到面试题,我们来分析**
 这个面试题,如果我们没有面向对象,面向抽象的概念, 那我们应该很快就能拿起键盘了,一个停车场,三个普通车位,一个豪华车位,一个摄像头,一个大屏幕显示器,各种各样的车,可能我们很快就能做完,‘设计完’,毕竟面向具体是真的很简单,要求什么我就做什么。。。
 不过说回来,如果面试官再让你减一个车位或者增加两个豪华车位,加两个摄像头?如果按照我们之前的来写,简单。。。改一下不就行了,加一个豪华车位,加两个摄像头。。。其实到这里想必已经凉凉了。
 下面我们来使用面向对象
 类图这里就不再画了
 首先面试题中所提到的我们都可以看成类,比如停车场是一个类吧,它里面的车位是一个类吧,摄像头,屏幕。。。我们都可以看做是类
 
 停车场,有层位,有摄像头,屏幕,所以我们先来创建一个停车场,这一类
 
 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里,直接运行打开,大家只要看各个类之间的联系就可以,具体到行为的逻辑代码只是怎么简单想怎么写就怎么写的,当然也有没考虑全面的,比如各个车位的价格应该也是动态的,为了赶时间,好多东西我都直接定死了。

抽象好了之后,这样不论是增加减少变更价钱我们都可以灵活地处理,每个类最基础的行为和方法几乎是不变得,我们只需要变容易变得抽象起来,封装起来。之后, 就变得‘简单’

欢迎一起探讨,大家共同进步!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Agile Web Application Development with Yii 1.1 and PHP5

Agile Web Application Development with Yii 1.1 and PHP5

Jeffrey Winesett / Packt Publishing / 2010-08-27

In order to understand the framework in the context of a real-world application, we need to build something that will more closely resemble the types of applications web developers actually have to bu......一起来看看 《Agile Web Application Development with Yii 1.1 and PHP5》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具