1. 什么是面向对象
把客观对象抽象成属性数据和对数据的相关操作,把内部细节和不想关的信息隐藏起来,把同一个类型的客观对象的属性数据和操作绑定在一起,封装成类,并且允许分成不同层次进行抽象,通过继承实现属性和操作的共享
- 面向对象的分析 OOA
- 面向对象的设计 OOD
- 面向对象的编程 OOP
1.1 概念
类、对象(实例)
父类是公共的
class Animal{
constructor(name) {
this.name=name;
}
eat() {
console.log(`${this.name} eat`)
}
}
let animal=new Person('动物');
animal.eat();
1.2 继承
子类继承父类
继承可以把公共方法抽离出来,提高复用,减少冗余
class Animal{
constructor(name) {
this.name=name;
}
eat() {
console.log(`${this.name} eat`)
}
speak() {
}
}
let animal=new Animal('动物');
animal.eat();
class Dog extends Animal{
constructor(name,age) {
super(name);
this.age=age;
}
speak() {
console.log(`${this.name} is barking!`);
}
}
let dog=new Dog('🐶',5);
dog.eat();
dog.bark();
1.3 封装
把数据封装起来
减少耦合,不该外部访问的不要让外部访问
利于数据的接口权限管理
ES6 目前不支持,一般认为_开头的都会私有的,不要使用
实现
public:公有修饰符,可以在类内或者类外使用public修饰的属性或者行为,默认修饰符
protected:受保护的修饰符,可以本类和子类中使用protected修饰的属性和行为
private : 私有修饰符,只可以在类内使用private修饰的属性和行为
class Animal {
public name;
protected age;
private weight;
constructor(name,age,weight) {
this.name=name;
this.age=age;
this.weight=weight;
}
}
class Person extends Animal {
private money;
constructor(name,age,weight,money) {
super(name,age,weight);
this.money=money;
}
getName() {
console.log(this.name);
}
getAge() {
console.log(this.age);
}
getWeight() {
console.log(this.weight);
}
}
let p=new Person('zfpx',9,100,100);
console.log(p.name);
console.log(p.age);
console.log(p.weight);
module: {
rules: [
{
test: /\.js$/,
use: {
loader: 'babel-loader',
options: {
presets:["@babel/preset-env"]
}
}
},
{
test: /\.ts$/,
use: {
loader: 'ts-loader'
}
}
]
}
1.4 多态
同一个接口可以不同实现
保持子类的开放性和灵活性
面向接口编程
class Animal {
public name;
protected age;
private weight;
constructor(name,age,weight) {
this.name=name;
this.age=age;
this.weight=weight;
}
}
class Person extends Animal {
private money;
constructor(name,age,weight,money) {
super(name,age,weight);
this.money=money;
}
speak() {
console.log('你好!');
}
}
class Dog extends Animal {
private money;
constructor(name,age,weight) {
super(name,age,weight);
}
speak() {
console.log('汪汪汪!');
}
}
let p=new Person('zfpx',10,10,10);
p.speak();
let d=new Dog('zfpx',10,10);
d.speak();
2. 设计原则
2.1 什么是设计?
按哪一种思路或者标准来实现功能
功能相同,可以有不同设计的方式
需求如果不断变化,设计的作用才能体现出来
2.2 SOLID五大设计原则
首字母 指代 概念
S 单一职责原则 单一功能原则认为对象应该仅具有一种单一功能的概念。
O 开放封闭原则 开闭原则认为“软件体应该是对于扩展开放的,但是对于修改封闭的”的概念。
L 里氏替换原则 里氏替换原则认为“程序中的对象应该是可以在不改变程序正确性的前提下被它的子类所替换的”的概念。参考 契约式设计。
I 接口隔离原则 接口隔离原则认为“多个特定客户端接口要好于一个宽泛用途的接口”[5] 的概念。
D 依赖反转原则 依赖反转原则认为一个方法应该遵从“依赖于抽象而不是一个实例”[5] 的概念。依赖注入是该原则的一种实现方式。
2.2.1 S 单一职责原则
Single responsibility principle
一个程序只做好一件事
如果功能特别复杂就进行拆分
2.2.2 O 开放封闭原则
Open Closed Principle
对扩展开放,对修改关闭
增加需求时,扩展新代码,而非修改已有代码
这是软件设计的终极目标
src/utils/request.js
function parseJSON(response) {
return response.json();
}
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(response.statusText);
error.response = response;
throw error;
}
export default function request(url, options) {
return fetch(url, options)
.then(checkStatus)
.then(parseJSON)
.then(data=>{data})
.catch(err => ({ err }));
}
2.2.3 L 里氏替换原则
Liskov Substitution Principle
子类能覆盖父类
父类能出现的地方子类就能出现
JS使用比较少
2.2.4 I 接口隔离原则
Interface Segregation Principle
保持接口的单一独立,避免出现胖接口
JS中没有接口,使用较少
类似于单一职责原则,更关注接口
2.2.5 D 依赖倒置原则
Dependence Inversion Principle
面向接口编程,依赖于抽象而不依赖于具体实现
使用方只关注接口而不关注具体类的实现
JS中使用较少(没有接口,弱类型)
23种设计模式
3.1 创建型
- 工厂模式(工厂方法模式、抽象工厂模式、简单工厂模式)
- 建造者模式
- 单例模式
- 原型模式
3.2 结构型模式
- 适配器模式
- 装饰器模式
- 代理模式
- 外观模式
- 巧接模式
- 组合模式
- 享元模式
3.3 行为型
- 策略模式
- 模版方法模式
- 观察者模式
- 迭代器模式
- 职责链模式
- 命令模式
- 备忘录模式
- 状态模式
- 访问者模式
- 中介者模式
- 解释器模式