面向对象
继承:子类继承父类
封装:数据的权限和保密
多态:同一接口不同实现
// 父类
class People {
constructor(name, age) {
this.name = name
this.age = age
}
eat() {
alert(`${this.name} eat something`)
}
speak() {
alert(`${this.name}: age ${this.age}`)
}
}
// 子类继承父类
class Student extends People {
constructor(name, age, number){
super(name, age)
this.number = number
}
study() {
alert(`${this.name} study`)
}
}
// 实例
let xiaoming = new Student('xiaoming', 10, 'A1')
xiaoming.study()
xiaoming.eat()
let wangxin = new Student('wangxin', 10, 'A2')
wangxin.study()
wangxin.speak()
继承
People是父类,公共的,不仅仅服务于Student
继承可将公共方法抽离出来,提高复用,减少冗余
封装
(ES6尚不支持,TS支持)
定义属性关键字:
public: 完全开放;前面如果不写关键字,那么默认是public
protected: 对子类开放
private: 对自己开放
// 父类
class People {
name
age
protected weight // 对子类开放
constructor(name, age) {
this.name = name
this.age = age
this.weight = 120
}
eat() {
alert(`${this.name} eat something`)
}
speak() {
alert(`${this.name}: age ${this.age}`)
}
}
// 子类继承父类
class Student extends People {
number
private girlFriend
constructor(name, age, number){
super(name, age)
this.number = number
this.girlfriend = 'lu'
}
study() {
alert(`${this.name} study`)
}
getWeight() {
alert(`weight: ${this.weight}`)
}
}
// 实例
let xiaoming = new Student('xiaoming', 10, 'A1')
xiaoming.study()
xiaoming.eat()
xiaoming.getWeight()
xiaoming.girlFriend // 编译时会报错,直接会编译不通过!!!
let wangxin = new Student('wangxin', 10, 'A2')
wangxin.study()
wangxin.speak()
减少耦合,不该外露的不外露
利于数据、接口的权限管理
ES6 不支持,一般认为以_开头的属性是 private
多态
同一个接口,不同表现
JS应用极少
需要结合java等语言的接口、重写、重载等功能
// 父类
class People {
constructor(name, age) {
this.name = name
this.age = age
this.weight = 120
}
saySomething() {
}
}
class A extends People {
constructor(name) {
super(name)
}
saySomething() {
alert(`I am A : ${this.name}`)
}
}
class B extends People {
constructor(name) {
super(name)
}
saySomething() {
alert(`I am B : ${this.name}`)
}
}
let a = new A('a')
a.saySomething()
let b = new B('b')
b.saySomething()
保持子类的开放性和灵活性
面向接口编程
JS引用极少,了解即可
jQuery 应用举例
jQuery是一个class
$(‘p’)是jQuery的一个实例
class jQuery {
constructor(selector) {
let slice = Array.prototype.slice
let dom = slice.call(document.querySelectorAll(selector))
let len = len ? 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)
}
// 测试代码
var $p = $('p')
console.log($p)
console.log($p.addClass)
为何使用面向对象?
程序执行:顺序、判断、循环 ———— 结构化
面向对象 ———— 数据结构化
对于计算机,结构化的才是最简单的
编程:简单 & 抽象
UML 类图
Unified Modeling Language : 统一建模语言
UML包含很多种图,本章相关的是类图
关系
泛化:继承;空箭头
关联:引用: People 引用 House;实心箭头
演示,代码和类图的结合
MS Office Visio
// 父类
class People {
constructor(name, house) {
this.name = name
this.house = house
}
saySomething() {
}
}
class A extends People {
constructor(name, house) {
super(name, house)
}
saySomething() {
alert(`I am A : ${this.name}`)
}
}
class B extends People {
constructor(name, house) {
super(name, house)
}
saySomething() {
alert(`I am B : ${this.name}`)
}
}
class House {
constructor(city) {
this.city = city
}
showCity() {
alert(`house in : ${this.name}`)
}
}
let ahouse = new House('beijing')
let a = new A('a', ahouse)
a.saySomething()
let b = new B('b')
b.saySomething()
类图
类名
所有的属性:public 属性名A:类型
所有的方法:public 方法名A(参数1,参数2):返回值类型
‘+’: public
‘#’: protected
‘-‘: private
设计原则
即按照哪一种思路或者标准来实现功能
功能相同,可以有不同设计方案来实现
伴随着需求增加,设计的作用才能体现出来
《LINUX/UNIX设计哲学》
小即是美
让每个程序只做好一件事
快速建立原型
舍弃高效率而取可移植性(效率会因为硬件的升级而被抹平)
采用纯文本来存储数据
充分利用软件的杠杆效应(软件复用)
使用shell脚本来提高杠杆效应和可移植性
避免强制性的用户界面
让每个程序都成为过滤器
小准则:
允许用户定制环境
尽量使操作系统内核小而轻量化
使用小写字母并尽量简写
沉默是金
各部分之和大于整体
寻求90%的解决方案
ls | grep *.json | grep 'package'
5大设计原则
Single: 单一职责原则
一个程序只做好一件事
如果功能过于复杂
Open: 开放封闭原则
对扩展开放,对修改封闭
增加需求时,拓展新代码,而非修改已有代码
这是软件设计的终极目标
L: 李氏置换原则
子类能覆盖父类
父类能出现的地方子类就能出现
JS中使用较少(弱类型 & 继承使用较少)
Interface: 接口独立原则
保持接口的单一独立,避免出现“胖接口”
JS中没有接口(TS例外),使用较少
类似于单一职责原则,这里更关注接口
Dependence: 依赖倒置原则
面向接口编程,依赖于抽象而不依赖于具体
使用方只关注接口而不关注具体类的实现
JS中使用较少(没有接口 & 弱类型)
function loadImg(src) {
return new Promise((resolve, reject) => {
let img = document.createElement('img')
img.onload = () => {
resolve(img)
}
img.onerror = () => {
reject('图片加载失败')
}
img.src = src
})
}
let src = './img.png'
let result = loadImg(src)
result.then((img) => {
alert(`width: ${img.width}`)
return img
}).then((img) => {
alert(`height: ${img.height}`)
}).catch((err) => {
console.log(err)
})
从设计到模式
设计:指导思想
模式:结合日常开发总结出固定的模板
23种设计模式
创建型
组合型
行为型
面试题
打车时,可以打专车或者快车;
任何车都有车牌号和名称;
不同车价格不同,快车1元/km,专车2元/km;
行程开始时,显示车辆信息;
行程结束时,显示打车金额(假定行程就5km)。
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
}
start() {
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()
某停车场,分3层,每层100车位;
每个车位都能监控到车辆的驶入和离开;
车辆进入前,显示每层的空余车位数量;
车辆进入时,摄像头可识别车牌号和时间;
车辆出来时,出口显示器显示车牌号和停车时长。
设计模式
优先级:创建型 | 结构型 | 行为型
结合核心技术
结合框架应用
综合示例
设计方案
代码演示
设计模式对应(7种)