面向对象
概念
类
,具有相同或相似属性或方法的对象的抽象就是类。例如:人都有姓名、年龄,都会吃饭、说话,其中姓名、年龄就是人这个类的属性,吃饭、说话就是人这个类的方法。 对象
,类的具体实现就是对象。例如,小明这个人就可以认为是人这个类的具体实现。
// 类
class Person {constructor(name, age) {
this.name = name // 属性 姓名
this.age = age // 属性 年龄
}
// 方法 吃饭
eat() {alert(`${this.name} eat something.`)
}
// 方法 说话
speak() {alert(`My name is ${this.name}, my age is ${this.age}.`)
}
}
// 对象 Person 的具体实现
const xiaoming = new Person('xiaoming', 10)
xiaoming.eat()
xiaoming.speak()
三要素
继承
,子类可以继承父类的属性和方法。例如,学生是人类的一种,具有人类的所有特性,也可以有自己的特性,可以认为学生继承了人这个父类。
class Person {constructor(name, age) {
this.name = name
this.age = age
}
eat() {alert(`${this.name} eat something.`)
}
speak() {alert(`My name is ${this.name}, my age is ${this.age}.`)
}
}
// Student 继承了 Person,具有 Person 的所有属性,并且有自己的特有属性
class Student extends Person {constructor(name, age, no) {super(name, age)
this.no = no // 学生可以有学号属性
}
// 学生可以学习
study() {alert(`${this.name} study something.`)
}
}
const xiaoming = new Student('xiaoming', 10, '10010')
xiaoming.study()
封装
,类的属性具有访问权限。说到封装不得不说public、protected、private
三个关键字,其中 public
关键字修饰的属性表示公有的属性,可以随便访问,protected
关键字修饰的属性表示子类内部可以访问,private
关键字修饰的属性只能在类内部访问,外部无法访问(图中 +
表示共有属性、#
表示子类可以访问、-
表示私有属性,由于 javascript 不支持这三种修饰符,所以此处用 typescript 演示,了解即可)。
class Person {
public name // 公有属性,可以随便访问
public age
protected weight // 子类内部可以访问,外部无法访问
constructor(name, age) {
this.name = name
this.age = age
this.weight = 120
}
eat() {console.log(`${this.name} eat something.`)
}
speak() {console.log(`My name is ${this.name}, age is ${this.age}.`)
}
}
class Student extends Person {
private grilfriend // 私有属性,只有在 Student 类内部才可以访问
constructor(name, age) {super(name, age)
this.grilfriend = 'xiaoli'
}
study() {alert(`${this.name} study.`)
}
getWeight() {alert(`weight ${this.weight}.`) // protected 修饰的属性子类内部可以访问
}
}
let xiaoming = new Student('xiaoming', 10)
xiaoming.getWeight()
alert(xiaoming.name)
// alert(xiaoming.weight) // 报错
// alert(xiaoming.grilfriend) // 报错
多态
,子类既可以继承父类的属性和方法,也可以有自己的特性。学生是人类的一种,除了具有人类的所有特性之外,还可以有自己独特的特性,例如学生可以进行学习这个动作。
class Person {constructor(name) {this.name = name}
saySomething() {}
}
class A extends Person {constructor(name) {super(name)
}
saySomething() {alert('This is A.')
}
}
class B extends Person {constructor(name) {super(name)
}
saySomething() {alert('This is B.')
}
}
五大设计原则
单一职责原则
,应该有且只有一个引起变更的原因,一个程序只做一件事情,如果功能过于复杂,就要拆开,每部分保持独立。 开放封闭原则
,一个软件的实体,比如模块、类、对象应该对扩展开放,对修改封闭,增加新需求时要增加代码而不是修改代码。 里氏置换原则
现的地方,子类就可以出现,且替换成子类也不会产生任何错误或者异常。接口独立原则
接口,不要建立臃肿庞大的接口。即接口尽量细化,同时接口中的方法尽量少。依赖倒置原则
,面向接口编程,模块间的依赖关系通过接口和抽象类产生,实体类之间不直接发生依赖关系。 最少知识原则
统提供一个简单的入口,访问者或者客户不用了解系统内部的实现细节,只要懂得如何调用就好。
工厂模式
定义一个创建对象的工厂,将创建者和构造函数分离,创建者不用关心具体构造函数的实现,符合开放封闭原则和最少知识原则。
class Product {constructor(name) {this.name = name}
init() {console.log('init.')
}
fn() {console.log('fn.')
}
}
class Creator {create(name) {return new Product(name)
}
}
const creator = new Creator()
const obj = creator.create('obj')
obj.init()
obj.fn()
单例模式
系统中被唯一使用,一个类只有一个示例,例如:
- 登录框
- 购物车
class SingleObject {constructor() {}
init() {console.log('init...')
}
}
SingleObject.getInstance = (function() {
let instance = null
return function() {if (!instance) {instance = new SingleObject()
}
return instance
}
})()
const obj1 = SingleObject.getInstance()
obj1.init()
const obj2 = SingleObject.getInstance()
obj2.init()
console.log(obj1 === obj2)