面向对象

  • 三要素

  • 继承:子类继承父类

  • 封装:数据的权限和保密

  • 多态:同一接口不同实现

  1. // 父类
  2. class People {
  3. constructor(name, age) {
  4. this.name = name
  5. this.age = age
  6. }
  7. eat() {
  8. alert(`${this.name} eat something`)
  9. }
  10. speak() {
  11. alert(`${this.name}: age ${this.age}`)
  12. }
  13. }
  14. // 子类继承父类
  15. class Student extends People {
  16. constructor(name, age, number){
  17. super(name, age)
  18. this.number = number
  19. }
  20. study() {
  21. alert(`${this.name} study`)
  22. }
  23. }
  24. // 实例
  25. let xiaoming = new Student('xiaoming', 10, 'A1')
  26. xiaoming.study()
  27. xiaoming.eat()
  28. let wangxin = new Student('wangxin', 10, 'A2')
  29. wangxin.study()
  30. wangxin.speak()

继承

  • People是父类,公共的,不仅仅服务于Student

  • 继承可将公共方法抽离出来,提高复用,减少冗余

封装

(ES6尚不支持,TS支持)
定义属性关键字:

  • public: 完全开放;前面如果不写关键字,那么默认是public

  • protected: 对子类开放

  • private: 对自己开放

TypeScript

  1. // 父类
  2. class People {
  3. name
  4. age
  5. protected weight // 对子类开放
  6. constructor(name, age) {
  7. this.name = name
  8. this.age = age
  9. this.weight = 120
  10. }
  11. eat() {
  12. alert(`${this.name} eat something`)
  13. }
  14. speak() {
  15. alert(`${this.name}: age ${this.age}`)
  16. }
  17. }
  18. // 子类继承父类
  19. class Student extends People {
  20. number
  21. private girlFriend
  22. constructor(name, age, number){
  23. super(name, age)
  24. this.number = number
  25. this.girlfriend = 'lu'
  26. }
  27. study() {
  28. alert(`${this.name} study`)
  29. }
  30. getWeight() {
  31. alert(`weight: ${this.weight}`)
  32. }
  33. }
  34. // 实例
  35. let xiaoming = new Student('xiaoming', 10, 'A1')
  36. xiaoming.study()
  37. xiaoming.eat()
  38. xiaoming.getWeight()
  39. xiaoming.girlFriend // 编译时会报错,直接会编译不通过!!!
  40. let wangxin = new Student('wangxin', 10, 'A2')
  41. wangxin.study()
  42. wangxin.speak()
  • 减少耦合,不该外露的不外露

  • 利于数据、接口的权限管理

  • ES6 不支持,一般认为以_开头的属性是 private

多态

  • 同一个接口,不同表现

  • JS应用极少

  • 需要结合java等语言的接口、重写、重载等功能

  1. // 父类
  2. class People {
  3. constructor(name, age) {
  4. this.name = name
  5. this.age = age
  6. this.weight = 120
  7. }
  8. saySomething() {
  9. }
  10. }
  11. class A extends People {
  12. constructor(name) {
  13. super(name)
  14. }
  15. saySomething() {
  16. alert(`I am A : ${this.name}`)
  17. }
  18. }
  19. class B extends People {
  20. constructor(name) {
  21. super(name)
  22. }
  23. saySomething() {
  24. alert(`I am B : ${this.name}`)
  25. }
  26. }
  27. let a = new A('a')
  28. a.saySomething()
  29. let b = new B('b')
  30. b.saySomething()
  • 保持子类的开放性和灵活性

  • 面向接口编程

  • JS引用极少,了解即可

jQuery 应用举例

  • jQuery是一个class

  • $(‘p’)是jQuery的一个实例

  1. class jQuery {
  2. constructor(selector) {
  3. let slice = Array.prototype.slice
  4. let dom = slice.call(document.querySelectorAll(selector))
  5. let len = len ? dom.length : 0
  6. for (let i = 0; i < len; i++) {
  7. this[i] = dom[i]
  8. }
  9. this.length = len
  10. this.selector = selector || ''
  11. }
  12. append(node) {
  13. // ...
  14. }
  15. addClass(name) {
  16. // ...
  17. }
  18. html(data) {
  19. // ...
  20. }
  21. // ...
  22. }
  23. window.$ = function(selector) {
  24. // 工厂模式
  25. return new jQuery(selector)
  26. }
  27. // 测试代码
  28. var $p = $('p')
  29. console.log($p)
  30. console.log($p.addClass)

为何使用面向对象?

  • 程序执行:顺序、判断、循环 ———— 结构化

  • 面向对象 ———— 数据结构化

  • 对于计算机,结构化的才是最简单的

  • 编程:简单 & 抽象

UML 类图

  • Unified Modeling Language : 统一建模语言

  • UML包含很多种图,本章相关的是类图

  • 关系

    • 泛化:继承;空箭头

    • 关联:引用: People 引用 House;实心箭头

  • 演示,代码和类图的结合

  • MS Office Visio

  • ProcessOn

  1. // 父类
  2. class People {
  3. constructor(name, house) {
  4. this.name = name
  5. this.house = house
  6. }
  7. saySomething() {
  8. }
  9. }
  10. class A extends People {
  11. constructor(name, house) {
  12. super(name, house)
  13. }
  14. saySomething() {
  15. alert(`I am A : ${this.name}`)
  16. }
  17. }
  18. class B extends People {
  19. constructor(name, house) {
  20. super(name, house)
  21. }
  22. saySomething() {
  23. alert(`I am B : ${this.name}`)
  24. }
  25. }
  26. class House {
  27. constructor(city) {
  28. this.city = city
  29. }
  30. showCity() {
  31. alert(`house in : ${this.name}`)
  32. }
  33. }
  34. let ahouse = new House('beijing')
  35. let a = new A('a', ahouse)
  36. a.saySomething()
  37. let b = new B('b')
  38. b.saySomething()

类图

  • 类名

  • 所有的属性:public 属性名A:类型

  • 所有的方法:public 方法名A(参数1,参数2):返回值类型

  • ‘+’: public

  • ‘#’: protected

  • ‘-‘: private

设计原则

  • 何为设计?

  • 即按照哪一种思路或者标准来实现功能

  • 功能相同,可以有不同设计方案来实现

  • 伴随着需求增加,设计的作用才能体现出来

《LINUX/UNIX设计哲学》

  1. 小即是美

  2. 让每个程序只做好一件事

  3. 快速建立原型

  4. 舍弃高效率而取可移植性(效率会因为硬件的升级而被抹平)

  5. 采用纯文本来存储数据

  6. 充分利用软件的杠杆效应(软件复用)

  7. 使用shell脚本来提高杠杆效应和可移植性

  8. 避免强制性的用户界面

  9. 让每个程序都成为过滤器

小准则:

  1. 允许用户定制环境

  2. 尽量使操作系统内核小而轻量化

  3. 使用小写字母并尽量简写

  4. 沉默是金

  5. 各部分之和大于整体

  6. 寻求90%的解决方案

  1. ls | grep *.json | grep 'package'

5大设计原则

  • Single: 单一职责原则

    • 一个程序只做好一件事

    • 如果功能过于复杂

  • Open: 开放封闭原则

    • 对扩展开放,对修改封闭

    • 增加需求时,拓展新代码,而非修改已有代码

    • 这是软件设计的终极目标

  • L: 李氏置换原则

    • 子类能覆盖父类

    • 父类能出现的地方子类就能出现

    • JS中使用较少(弱类型 & 继承使用较少)

  • Interface: 接口独立原则

    • 保持接口的单一独立,避免出现“胖接口”

    • JS中没有接口(TS例外),使用较少

    • 类似于单一职责原则,这里更关注接口

  • Dependence: 依赖倒置原则

    • 面向接口编程,依赖于抽象而不依赖于具体

    • 使用方只关注接口而不关注具体类的实现

    • JS中使用较少(没有接口 & 弱类型)

  1. function loadImg(src) {
  2. return new Promise((resolve, reject) => {
  3. let img = document.createElement('img')
  4. img.onload = () => {
  5. resolve(img)
  6. }
  7. img.onerror = () => {
  8. reject('图片加载失败')
  9. }
  10. img.src = src
  11. })
  12. }
  13. let src = './img.png'
  14. let result = loadImg(src)
  15. result.then((img) => {
  16. alert(`width: ${img.width}`)
  17. return img
  18. }).then((img) => {
  19. alert(`height: ${img.height}`)
  20. }).catch((err) => {
  21. console.log(err)
  22. })

从设计到模式

  • 设计:指导思想

  • 模式:结合日常开发总结出固定的模板

23种设计模式

  • 创建型

  • 组合型

  • 行为型

面试题

打车时,可以打专车或者快车;
任何车都有车牌号和名称;
不同车价格不同,快车1元/km,专车2元/km;
行程开始时,显示车辆信息;
行程结束时,显示打车金额(假定行程就5km)。

  1. class Car {
  2. constructor(number, name) {
  3. this.number = number
  4. this.name = name
  5. }
  6. }
  7. class KuaiChe extends Car {
  8. constructor(number, name) {
  9. super(number, name)
  10. this.price = 1
  11. }
  12. }
  13. class ZhuanChe extends Car {
  14. constructor(number, name) {
  15. super(number, name)
  16. this.price = 2
  17. }
  18. }
  19. class Trip {
  20. constructor(car) {
  21. this.car = car
  22. }
  23. start() {
  24. console.log(`行程开始 名称:${this.car.name} 车牌号:${this.car.number}`)
  25. }
  26. end() {
  27. console.log(`行程结束 价格:${this.car.price} * 5`)
  28. }
  29. }
  30. let car = new KuaiChe(100, '桑塔纳')
  31. let trip = new Trip(car)
  32. trip.start()
  33. trip.end()

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

设计模式

  • 优先级:创建型 | 结构型 | 行为型

  • 结合核心技术

  • 结合框架应用

综合示例

  • 设计方案

  • 代码演示

  • 设计模式对应(7种)