面向对象三要素:
- 继承,子类继承父类
- 封装,数据的权限和保密
- public 完全开放
- protected 对子类开放
- private 对自己开放
注意: es6不支持,可以使用ts或其他面向对象语言
特点: 减少耦合;利于数据,接口的权限管理;es6目前不支持,一般_
开头的属性是private
- 多态,同一接口,不同实现
- js应用极少
- 需要结合java等语言的接口,重写,重载等功能
特点:保持子类的开放性和灵活性;面向接口编程;
为什么使用?
数据结构化,编程:简单 & 抽象
UML类图
关系:
- 泛化,表示继承 (空心箭头)
- 关联,表示引用 (实心箭头)
设计原则
1. 何为设计?
推荐书籍:《UNIX/LINUX设计哲学》
描述:
- 按照哪一种思路或者标准来实现功能
- 功能相同,可以有不同设计方案来实现
- 伴随需求增加,设计的作用才能体现出来
设计准则:
- 小即是美
- 让每个程序只做好一件事
- 快速建立原型
- 舍弃高效率而取可移植性
- 采用纯文本来存储数据
- 充分利用软件的杠杆效应(软件复用)
- 使用shell脚本来提高杠杆效应和可移植性
- 避免强制性的用户界面
- 让每个程序都称为过滤器
小准则:
- 允许用户定制环境
- 尽量使操作系统内核小而轻量化
- 使用小写字母并尽量简短;
- 沉默是金;(举例:一个方法,要求传入数字,处理后输出数字;如果传入或输出的不是数字,就什么都不要输出或者输出0)
- 各部分之和大于整体
- 寻求90%的解决方案 (二八定律:花20%的成本解决80%的需求。剩下20%的需求可能要花很大的成本,没有必要做到完美)
设计原则
SOLID五大设计原则
- S - 单一职责原则
- O- 开放封闭原则 (对扩展开放,对修改封闭)
- L - 李氏置换原则
- I - 接口独立原则
- D - 依赖导致原则 (依赖抽象,接口,而不是具体的实现)
S - 单一职责原则
- 一个程序只做好一件事
- 如果功能过于复杂就拆分开,每个部分保持独立
O - 开放封闭原则
- 对扩展开放,对修改封闭
- 增加需求时,扩展新代码,而非修改已有代码
L - 李氏置换原则
- 子类能覆盖父类
- 父类能出现的地方,子类就能出现
- JS中使用较少(弱类型 & 继承使用较少)
I - 接口独立原则
- 保持接口的单一独立,避免出现“胖接口” (并不是百分之百不能出现)
- JS中没有接口(typescript例外),使用较少
- 类似与单一职责原则,这里更关注接口
D - 依赖导致原则
- 面向接口编程,依赖于抽象而不依赖于具体
- 使用方只关注接口而不关注具体类的实现
- JS中使用较少(没有接口&弱类型)
注意:由于前端的业务场景和JS的语法限制,SO体现较多,LID体现较少
设计模式
23种设计模式
- 创建型
- 工厂模式(工厂方法模式,抽象工厂模式,建造者模式)
- 单例模式
- 原型模式
- 结构型
- 适配器模式
- 装饰器模式
- 代理模式
- 外观模式
- 桥接模式
- 组合模式
- 享元模式
- 行为型
- 策略模式
- 模版方法模式
- 观察者模式
- 迭代器模式
- 职责链模式
- 命令模式
- 备忘录模式
- 状态模式
- 访问者模式
- 中介者模式
- 解释器模式
如何学习设计模式?
- 明白每个设计的道理和用意
- 通过经典应用体会它的真正使用场景
- 自己编码时多思考,尽量模仿
关键词:刻意训练
面试题示例
第一题:
- 打车时,可以打专车或者快车。任何车都有车牌号和名称。
- 不同车价格不同,快车每公里1元,专车每公里2元。
- 行程开始时,显示车辆信息。
- 行程结束时,显示打车金额(假定行程就5公里)
画出UML类图 用ES6语法写出该示例
class Car {
constructor (numPlate, name) {
this.numPlate = numPlate // 车牌
this.name = name // 车名
}
}
class privateCar extends Car {
constructor (numPlate, name) {
super(numPlate, name)
this.price = 2
}
}
class expressTrain extends Car {
constructor (numPlate, name) {
super(numPlate, name)
this.price = 1
}
}
class Trip {
constructor (car) {
this.car = car
}
start () {
console.log(`行程开始, 名称:${this.car.name}, 车牌号:${this.car.price}`)
}
end () {
console.log(`行程结束,价格${this.car.price * 5}`)
}
}
const car = new privateCar('k1234', '小蓝车')
const trip = new Trip(car)
trip.start()
trip.end()
第二题:
- 某停车场,分3层,每层100车位
- 每个车位都能监控到车辆的驶入和离开
- 车辆进入前,显示每层的空余车位数量
- 车辆进入时,摄像头可以识别车牌号和时间
- 车辆出来时,出口显示器显示车牌号和停车时长
画出UML类图
//车辆
class Car {
constructor(num) {
this.num = num
}
}
// 摄像头
class Camera {
shot(car) {
return {
num: car.num,
inTime: Date.now()
}
}
}
// 出口显示屏
class Screen {
show(car, inTime) {
console.log(`车牌号:${car.num}`)
console.log(`停车时间 ${Date.now() - inTime}`)
}
}
// 停车场
class Park {
constructor(floors) {
this.floors = floors || []
this.camera = new Camera()
this.screen = new Screen()
this.carList = {} // 存储摄像头拍摄返回的车辆信息
}
in(car) {
// 通过摄像头获取信息
const info = this.camera.shot(car)
// 停到某个停车位
const i = parseInt(Math.random() * 100 % 100)
const place = this.floors[0].places[i]
place.in()
info.place = place
// 记录信息
this.carList[car.num] = info
}
out(car) {
// 获取信息
const info = this.carList[car.num]
// 将停车位清空
const place = info.place
place.out()
// 显示时间
this.screen.show(car, info.inTime)
// 清空记录
delete this.carList[car.num]
}
emptyNum() {
return this.floors.map(floor => {
return `${floor.index}层还有${floor.emptyPlaceNum()}个空余车位`
}).join('\n')
}
}
// 层
class Floor {
constructor(index, places) {
this.index = index
this.places = places || []
}
emptyPlaceNum() {
let num = 0
this.places.forEach(p => {
if (p.empty) {
num += 1
}
})
return num
}
}
// 车位
class Place {
constructor() {
this.empty = true
}
in() {
this.empty = false
}
out() {
this.empty = true
}
}
// 测试
// 初始化停车场
const floors = []
for(let i = 0; i < 3; i++) {
const places = []
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)