前端设计模式面试题

300 阅读3分钟

面试题一

面试题描述:

  • 打车时,可以打快车和专车,任何车都有车牌号和名称
  • 不同车的价格不同,快车每公里1元,专车每公里2元
  • 行程开始时,显示车辆信息
  • 行程结束时,显示打车金额(假定行程就是5公里)

翻译上面的语句:

  • 车分为快车和专车,可以定义一个车的接口,接着定义快车和专车两个类,这两个类 implement 这个接口,这个接口有三个属性,车牌号、名称、价格。
  • 把行程单独设置为一个类,它要显示车辆信息,因此有一个车辆的属性,属性值类型为定义的接口Car,然后有两个方法,开始与结束的方法。

image.png

interface Car {
  name: string
  number: number
  price: number
}

class KuaiCar implements Car {
  name: string
  number: number
  price: number
  constructor(name: string, number: number) {
    this.name = name
    this.number = number
    this.price = 1
  }
}

class ZhuanCar implements Car {
  name: string
  number: number
  price: number
  constructor(name: string, number: number) {
    this.name = name
    this.number = number
    this.price = 2
  }
}

class Trip {
  car: Car
  constructor(car: Car) {
    this.car = car
  }
  start() {
    console.log('行程开始', this.car.name, this.car.number)
  }
  end() {
    console.log('行程结束', this.car.price * 5)
  }
}

const kuai = new KuaiCar('大众', 88888)
const zhuan = new ZhuanCar('宝马', 77777)

const trip = new Trip(zhuan)
trip.start()
trip.end()

面试题二

面试题描述:

  • 某停车场,分3层,每层100个车位
  • 每个车位都能监控到车辆的驶入与离开
  • 车辆进入前,显示每层的空余车位数量
  • 车辆进入时,摄像头可识别车牌号和时间
  • 车辆出来时,出口显示屏显示车牌号和停车时长

翻译上面的语句:

  • 首先要定义三个类,分别是停车场、层和车位
  • 接着定义一个车辆的类,同时车位有一个属性来表示是否为空,并有个方法来监控车辆的驶入和离开,这样就完善了车位的属性和方法
  • 车辆进入前,面对的是停车场,显示每层的空余车位数量应该由停车场来显示,所以停车场这个类有个方法来显示空位数量,但是每层的空位数量还是由层这个类来显示,停车场只是汇总来显示。
  • 定义一个摄像头的类,摄像头输入的是车辆,输出的是车牌号和时间,输出的内容往哪里存呢?肯定是往停车场存,所以停车场还要加一个属性,用来存储车辆列表
  • 定义一个显示器的类,显示器输入一个车牌号,然后根据车辆进入的时间输出总共停车时长

image.png

class Place {
  empty: boolean
  constructor() {
    this.empty = true
  }
  in() {
    this.empty = false
  }
  out() {
    this.empty = true
  }
}

class Floor {
  places: Array<Place>
  index: number
  constructor(index: number, places: Array<Place>) {
    this.index = index
    this.places = places
  }
  emptyPlaceNum() {
    let num = 0
    for (let i = 0; i < this.places.length; i++) {
      if (this.places[i].empty) {
        num = num + 1
      }
    }
    return num
  }
}

class Car {
  num: number
  constructor(num: number) {
    this.num = num
  }
}

interface CarInfo {
  num: number
  inTime: number
  place?: Place
}

class Camera {
  shot(car: Car): CarInfo {
    return {
      num: car.num,
      inTime: Date.now()
    }
  }
}

class Scren {
  show(car: Car, inTime: number) {
    console.log('车牌号:', car.num)
    console.log('停车时间', Date.now() - inTime)
  }
}

class Park {
  floors: Array<Floor>
  // 存储摄像头拍摄返回的车辆信息
  carList: Record<number, CarInfo>
  camera: Camera
  screen: Scren
  constructor(floors: Array<Floor>) {
    this.floors = floors
    this.carList = {}
    this.camera = new Camera()
    this.screen = new Scren()
  }
  emptyNum() {
    return this.floors
      .map(floor => {
        return `${floor.index}层还有${floor.emptyPlaceNum()}个车位`
      })
      .join('/n')
  }
  in(car: Car) {
    // 通过摄像头获取车辆信息
    const info = this.camera.shot(car)
    // 停到某个停车位
    const i = parseInt(String((Math.random() * 100) % 100))
    // 假设停在第一层
    const place = this.floors[0].places[i]
    place.in()
    info.place = place
    // 记录车辆信息
    this.carList[car.num] = info
  }
  out(car: Car) {
    // 获取车辆信息
    const info = this.carList[car.num]
    // 将停车位清空
    const place = info?.place
    place?.out()
    // 显示时间
    this.screen.show(car, info.inTime)
    // 删除车辆信息
    delete this.carList[car.num]
  }
}

// 测试
// 初始化停车场
const floors: Array<Floor> = []
for (let i = 0; i < 3; i++) {
  const places: Array<Place> = []
  for (let j = 0; j < 100; j++) {
    places[j] = new Place()
  }
  floors[i] = new Floor(i + 1, places)
}

const park = new Park(floors)

// 初始化车辆
const car1 = new Car(100)
const car2 = new Car(200)
const car3 = new Car(300)

console.log('第一辆车进入')
console.log(park.emptyNum())
park.in(car1)

console.log('第二辆车进入')
console.log(park.emptyNum())
park.in(car2)

console.log('第一辆车离开')
park.out(car1)

console.log('第二辆车离开')
park.out(car2)

console.log('第三辆车进入')
console.log(park.emptyNum())
park.in(car3)

console.log('第三辆车离开')
park.out(car3)