Javascript 设计模式系统讲解与应用——学习笔记1

面向对象三要素:

  1. 继承,子类继承父类
  2. 封装,数据的权限和保密
    • public 完全开放
    • protected 对子类开放
    • private 对自己开放

注意: es6不支持,可以使用ts或其他面向对象语言
特点: 减少耦合;利于数据,接口的权限管理;es6目前不支持,一般_开头的属性是private

  1. 多态,同一接口,不同实现
    • js应用极少
    • 需要结合java等语言的接口,重写,重载等功能
      特点:保持子类的开放性和灵活性;面向接口编程;

为什么使用?
数据结构化,编程:简单 & 抽象

UML类图

关系:

  1. 泛化,表示继承 (空心箭头)
  2. 关联,表示引用 (实心箭头)

设计原则

1. 何为设计?

推荐书籍:《UNIX/LINUX设计哲学》

描述:
  1. 按照哪一种思路或者标准来实现功能
  2. 功能相同,可以有不同设计方案来实现
  3. 伴随需求增加,设计的作用才能体现出来
设计准则:
  1. 小即是美
  2. 让每个程序只做好一件事
  3. 快速建立原型
  4. 舍弃高效率而取可移植性
  5. 采用纯文本来存储数据
  6. 充分利用软件的杠杆效应(软件复用)
  7. 使用shell脚本来提高杠杆效应和可移植性
  8. 避免强制性的用户界面
  9. 让每个程序都称为过滤器
小准则:
  1. 允许用户定制环境
  2. 尽量使操作系统内核小而轻量化
  3. 使用小写字母并尽量简短;
  4. 沉默是金;(举例:一个方法,要求传入数字,处理后输出数字;如果传入或输出的不是数字,就什么都不要输出或者输出0)
  5. 各部分之和大于整体
  6. 寻求90%的解决方案 (二八定律:花20%的成本解决80%的需求。剩下20%的需求可能要花很大的成本,没有必要做到完美)
设计原则
SOLID五大设计原则
  1. S - 单一职责原则
  2. O- 开放封闭原则 (对扩展开放,对修改封闭)
  3. L - 李氏置换原则
  4. I - 接口独立原则
  5. D - 依赖导致原则 (依赖抽象,接口,而不是具体的实现)

S - 单一职责原则

  • 一个程序只做好一件事
  • 如果功能过于复杂就拆分开,每个部分保持独立

O - 开放封闭原则

  • 对扩展开放,对修改封闭
  • 增加需求时,扩展新代码,而非修改已有代码

L - 李氏置换原则

  • 子类能覆盖父类
  • 父类能出现的地方,子类就能出现
  • JS中使用较少(弱类型 & 继承使用较少)

I - 接口独立原则

  • 保持接口的单一独立,避免出现“胖接口” (并不是百分之百不能出现)
  • JS中没有接口(typescript例外),使用较少
  • 类似与单一职责原则,这里更关注接口

D - 依赖导致原则

  • 面向接口编程,依赖于抽象而不依赖于具体
  • 使用方只关注接口而不关注具体类的实现
  • JS中使用较少(没有接口&弱类型)

注意:由于前端的业务场景和JS的语法限制,SO体现较多,LID体现较少

设计模式

23种设计模式

  1. 创建型
    • 工厂模式(工厂方法模式,抽象工厂模式,建造者模式)
    • 单例模式
    • 原型模式
  2. 结构型
    • 适配器模式
    • 装饰器模式
    • 代理模式
    • 外观模式
    • 桥接模式
    • 组合模式
    • 享元模式
  3. 行为型
    • 策略模式
    • 模版方法模式
    • 观察者模式
    • 迭代器模式
    • 职责链模式
    • 命令模式
    • 备忘录模式
    • 状态模式
    • 访问者模式
    • 中介者模式
    • 解释器模式

如何学习设计模式?

  • 明白每个设计的道理和用意
  • 通过经典应用体会它的真正使用场景
  • 自己编码时多思考,尽量模仿
    关键词:刻意训练
面试题示例

第一题:

  • 打车时,可以打专车或者快车。任何车都有车牌号和名称。
  • 不同车价格不同,快车每公里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)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神小夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值