1. 犀牛前端部落首页
  2. JS教程

JavaScript设计原则

面向对象

概念

// 类,即模版
class People {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  eat() {}
  speak() {}
}

三要素

  • 继承,子类继承父类
// 父类
class People {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  eat() {}
  speak() {}
}

// 子类继承父类
class Student extends People {
  constructor(name, age, number) {
    super(name, age)
    this.number = number
  }
  study() {}
}
  • 封装,数据的权限和保密
// 父类
class People {
  name
  age
  protected weight // 受保护的属性,只有自己或者子类可以访问
  constructor(name, age) {
    this.name = name
    this.age = age
    this.weight = 120
  }
  eat() {}
  speak() {}
}

// 子类 继承父类
class Student extends People {
  number
  private girlfriend
  constructor(name, age, number) {
    super(name, age)
    this.number = number
    this.girlfriend = 'xiaoli'
  }
  study() {}
  getWeight() {
    console.log(this.weight)
  }
}
  • 多态,同一接口不同实现
class People {
  constructor(name) {
    this.name = name
  }
  saySomething() {}
}

class A extends People {
  constructor(name) {
    super(name)
  }
  saySomething() {
    console.log("A")
  }
}

class B extends People {
  constructor(name) {
    super(name)
  }
  saySomething() {
    console.log("B")
  }
}

JS应用

class jQuery {
  constructor(selector) {
    let slice = Array.prototype.slice
    let dom = slice.call(document.querySelectorAll(selector))
    let len = dom ? dom.length : 0
    for(let i = 0; i < len; i++){
      this[i] = dom[i]
    }
    this.length = len
    this.selector = selector || ''
  }
  append(node) {}
  addClass(name) {}
  html(data) {}
}
window.$ = function(selector) {
  // 工厂模式
  return new jQuery(selector)
}

面向对象的意义

  • 程序执行:顺序、判断、循环——结构化
  • 面向对象——数据结构化
  • 对于计算机,结构化的才是最简单的

UML类图

  • 泛化,表示继承
  • 关联,表示引用
JavaScript设计原则
class People {
  constructor(name, house) {
    this.name = name
    this.house = house
  }
  saySomething() {}
}

class A extends People {
  constructor(name, house) {
    super(name, house)
  }
  saySomething() {
    console.log("A")
  }
}

class B extends People {
  constructor(name, house) {
    super(name, house)
  }
  saySomething() {
    console.log("B")
  }
}

class House {
  constructor(city) {
    this.city = city
  }
  showCity() {
    console.log(this.city)
  }
}
let aHouse = new House('上海')
let a = new A('a', aHouse)
let b = new B('b')

设计原则

准则

  • 小即是美
  • 让每个程序只做好一件事
  • 快速建立原型
  • 舍弃高效率而取可移植性
  • 采用纯文本来存储数据
  • 充分利用软件的杠杆效应(软件复用)
  • 使用shell脚本来提高杠杆效应和可移植性
  • 避免强制性的用户界面
  • 让每个程序都成为过滤器

小准则

  • 允许用户定制环境
  • 尽量使操作系统内核小而轻量化
  • 使用小写字母并尽量简短
  • 沉默是金
  • 各部分之和大于整体
  • 寻求90%的解决方案

SOLID五大设计原则

  • S-单一职责原则
    • 一个程序只做好一件事
    • 如果功能过于复杂就拆分开,每个部分保持独立
  • O-开放封闭原则
    • 对扩展开放,对修改封闭
    • 增加需求时,扩展新代码,而非修改已有代码
  • L-里氏置换原则
    • 子类能覆盖父类
    • 父类能出现的地方子类就能出现
    • JS中使用较少(弱类型&继承使用较少)
  • I-接口独立原则
    • 保持接口的单一独立,避免出现“胖接口”
    • JS中没有接口(typescript例外),使用较少
    • 类似单一职责原则
  • D-依赖导致原则
    • 面向接口编程,依赖于抽象而不依赖于具体
    • 使用方只关注接口而不关心具体类的实现
    • JS中使用较少(没有接口&弱类型)

设计模式

创建型

  • 工厂模式(工厂方法模式,抽象工厂模式,建造者模式)
  • 单例模式
  • 原型模式

结构型

  • 适配器模式
  • 装饰器模式
  • 代理模式
  • 外观模式
  • 桥接模式
  • 组合模式
  • 享元模式

行为型

  • 策略模式
  • 模板方法模式
  • 观察者模式
  • 迭代器模式
  • 职责链模式
  • 命令模式
  • 备忘录模式
  • 状态模式
  • 访问者模式
  • 中介模式
  • 解释器模式

面试题

  • 打车时,可以打专车或者快车。任何车都有车牌号和名称
  • 不同车价格不同,快车每公里1元,专车每公里2元
  • 行程开始时,显示车辆信息
  • 行程结束时,显示打车金额(假定行程就5公里)
JavaScript设计原则
// 车 父类
class Car {
  constructor(number, name) {
    this.number = number
    this.name = name
  }
}
//快车
class Kuaiche extends Car {
  constructor(number, name){
    super(number, name)
    this.price = 1
  }
}
// 专车
class Zhuanche extends Car {
  constructor(number, name) {
    super(number, name)
    this.price = 2
  }
}
// 行程
class Trip {
  constructor(car) {
    this.car = car
  }
  star() {
    console.log(this.car.name,this.car.number)
  }
  end() {
    console.log(this.car.price * 5)
  }
}
// 测试
let car = new Kuaiche(100, '桑塔纳')
let trip = new Trip(car)
trip.start()
trip.end()
  • 某停车场,分三层,每层100车位
  • 每个车位都能监控到车辆的驶入和离开
  • 车辆进入前,显示每层的空余车位数量
  • 车辆进入时,摄像头可识别车牌号和时间
  • 车辆出来时,出口显示器显示车辆车牌号和停车时长
JavaScript设计原则
// 车辆
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, 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()
    })
  }
}
// 层
class Floor {
  constructor(index, places) {
    this.index = index
    this.places = places || []
  }
  emptyPlaceNum() {
    let num = 0
    this.places.forEach(p => {
      if(p.empty){
        num = 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)

park.emptyNum()
park.in(car1)
park.out(car1)

原创文章,作者:犀牛前端部落,如若转载,请注明出处:https://www.pipipi.net/4351.html

发表评论

登录后才能评论