设计模式
五大设计原则 SOLID
- S 单一职责原则
- O 开闭原则,对扩展开放,对修改关闭
- L 里氏置换原则,子类覆盖父类
- I 接口独立原则,迪米特法则,最少知识原则
- D 依赖倒置原则,高层模块不应该依赖低层模块,两者都应该依赖其抽象
面向对象三要素
- 继承 - 子类继承父类,复用性
- 封装 - 数据的权限管理,减少耦合
- 多态 - 同一接口的不同实现,保持子类的开放性和灵活性
面向对象的继承
- public - 完全开放,子类和实例都可访问
- protected - 仅子类可访问,实例不能访问
- private - 仅该类内部可访问,子类和实例均不能访问
- static - 仅能通过类名调用,子类和实例不能访问,可被继承,继承后可通过子类类名调用
- abstract - 抽象类,用于抽象方法和属性,在类名和需要抽象的方法或属性前加 abstract 关键词,不能被实例化,子类中必须实现抽象的方法和属性
简单工厂模式
将 new 的操作进行单独封装
- 示例
window.$()
React.creatElement()
- 经典结构
class Product {
fun1(){}
}
class Creator {
create () {
return new Product()
}
}
const creator = new Creator()
const p1 = creator.create()
p1.fun1()
- 优势
工厂函数内的构造函数发生变化时方便修改
单例模式
一个类只能有一个实例,并提供一个访问它的全局访问点。
- 示例
window.$
vuex 和 redux
- 经典结构
// js 通过闭包来模拟,注意不能 new 。懒汉式单例,在调用的时候实例化
class SingleObject {
static getInstance = (() => {
let instance;
return () => {
if (!instance) {
instance = new SingleObject();
}
return instance;
};
})();
}
// 饿汉式单例,在类加载的时候就实例化
class SingleObject {
static instance = new SingleObject();
static getInstance = () => {
return SingleObject.instance;
};
}
const s1 = SingleObject.getInstance();
const s2 = SingleObject.getInstance();
console.log(s1 === s2); // true
// ts 版
class SingleObject {
static instance: SingleObject;
static instance() {
if (!SingleObject.instance) {
SingleObject.instance = new SingleObject();
}
return SingleObject.instance;
}
}
const aa = SingleObject.instance();
const bb = SingleObject.instance();
console.log(aa === bb);
代理模式
为其他对象提供一种代理以控制对这个对象的访问。
装饰器模式
为 类/对象 添加新功能
- 适配器模式: 提供同一功能不同的接口
- 代理模式: 提供一模一样的接口
- 装饰器模式:原有功能不变且直接可用,扩展功能
外观模式
为子系统的一组接口提供一个高层接口
迭代器模式
顺序访问一个集合,把集合包装成一个迭代器,通过 next()
来顺序访问
观察者模式
// 发布-订阅模式
class Watcher {
constructor () {
this.listeners = new Map()
}
emit (type, ...arg) {
const events = this.listeners.get(type)
if(events) {
events.forEach(ev => ev(...arg))
}
}
on (type, callback) {
const events = this.listeners.get(type)
if(events) {
events.push(callback)
} else {
this.listeners.set([callback])
}
}
}
// 发布-订阅模式 TS 版
class Watcher {
private m_lisneners: Map<string, ((...arg)=>void)[]>
constructor () {
this.m_lisneners = new Map()
}
on (name: string, event: (...arg)=>void) {
const eventObj = this.m_lisneners.get(name)
if (eventObj) {
eventObj.push(event)
} else {
this.m_lisneners.set(name, [ event ])
}
}
emit (name, ...arg) {
const eventObj = this.m_lisneners.get(name)
if (eventObj) {
eventObj.forEach((callback: (...arg)=>void) => {
callback(...arg)
})
}
}
}
原型模式
clone 自己生成一个新对象,实例上提供 clone()
方法
例:Object.create
命令模式
将一个操作封装成对象,对操作进行排序并记录操作日志,并且操作可撤销。
建造者模式
将一个复杂对象的构建与它的表示分离,例如 absrtuct .
备忘录模式
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可以将该对象恢复到之前保存的状态。