在面向对象语言中,针对特定问题的解决方案(简洁&优雅)
以下模式以js展开。
工厂模式
调用函数,该函数返回一个新对象。
eg1(es5):
function FoodFactory(name,color){
return {
name,
color
}
}
cosnt food = FoodFactory('土豆','yellow')
eg2(es6+):
class Product {
constructor(name) {
this.name = name
}
init() {
console.log('init')
}
fun() {
console.log('fun')
}
}
let factory = new Factory() // 返回一个实例对象
应用:
- axios.create()自定义参数配置
单例模式
整个系统中,只有一个该单例对象存在。
class SingleTon {
static #instance;
static getInstance(){
if(!this.#instance){
this.#instance = new SingleTon();
}
return this.#instance
}
}
const s1 = SingleTon.getInstance();
const s2 = SingleTon.getInstance();
console.log(s1 === s2); //true
应用:
- 登录框
- vuex 和 redux中的store
- 全局toast
观察者模式
在对象之间定义一个一对多的依赖,当对象状态发生改变时,所有依赖该对象的都会收到通知。(将自身当作发布者)
// 主题 保存状态,状态变化之后触发所有观察者对象
class Subject {
constructor() {
this.state = 0
this.observers = []
}
getState() {
return this.state
}
setState(state) {
this.state = state
this.notifyAllObservers()
}
notifyAllObservers() {
this.observers.forEach(observer => {
observer.update()
})
}
attach(observer) {
this.observers.push(observer)
}
}
// 观察者
class Observer {
constructor(name, subject) {
this.name = name
this.subject = subject
this.subject.attach(this)
}
update() {
console.log(`${this.name} update, state: ${this.subject.getState()}`)
}
}
// 测试
let s = new Subject()
let o1 = new Observer('o1', s)
let o2 = new Observer('02', s)
s.setState(12)
应用:
- addEventListener(' ', () => {})
发布订阅模式
与观察者模式类似,区别在于观察者模式无中间商,发布订阅存在中间商Event Bus(事件总线)管理注册、订阅、移除事件等。
class Emitter {
#handlers = { };
$on(event, callback){
if(this.#handlers[event] == undefined){
this.#handlers[event] = [];
}
this.#handlers[event].push(callback);
}
$emit(event,...args){
const funcs = this.#handlers[event] || [];
funcs.forEach(callback => callback(...args));
}
$off(event){
this.#handlers[event] = undefined;
}
}
const bus = new Emitter();
bus.$on('event1', (...args) => { console.log('111',...args);});
bus.$on('event1', (...args) => { console.log('222',...args);});
bus.$emit('event1','hello','js');
bus.$on('event2', () => { console.log('333');});
bus.$emit('event2');
bus.$off('event2');
bus.$emit('event2');
应用:
- Vue2 EventBus
- Vue3 替代方案
原型模式
复制一个已经存在的实例来返回新的实例。
应用:
- Object.create()
let obj = {
name: '111',
fn1(){
console.log(this.name);
}
}
const newObj = Object.create(obj);
newObj.fn1(); // 111
console.log(newObj == obj); // false
代理模式
为一个对象提供一个代用品或占位符,以便控制对它的访问。
应用:
- ES6 的 proxy
- 缓存代理(如果有缓存走缓存,不需要再发送http请求,减少服务器压力)
迭代器模式
提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。
自定义对象可迭代,需要要遵循以下要求:
- 可迭代协议:增加方法
[Symbol.iterator](){}
,方法返回一个符合迭代器协议的对象。 - 迭代器协议:有next方法的对象,方法返回一个对象,包含done(Boolean) 和 value(any) 属性
eg:
const obj = {
[Symbol.iterator](){
const arr = ['北京','上海','深圳'];
let index = 0;
return {
next(){
if(index < arr.length){
return { done: false, value: arr[index++]};
}
return { done: true};
}
}
}
}
for(const value of obj){
console.log(value);
}