# 设计模式
# 工厂模式
- 特点
- 将new操作单独封装(new操作主要出现在面向对象创建实例的过程中)
- 遇到new时,就该考虑是否要使用工厂模式
- 示例
- 你去购买汉堡,直接点餐取餐,不用自己做
- 商店要’封装‘做汉堡的工作,做好直接给买者
- 代码演示
- 初始化一个产品类,再初始化一个工厂类,产品要给外部的人来用,但不直接暴露,而是通过工厂类将其暴露
class Product{
constructor(name){
this.name = name
}
init(){
console.log('init')
}
fn1(){
console.log('fn1')
}
fn2(){
console.log('fn2')
}
}
class Factor{
create(name){
return new Product(name)
}
}
let factor = new Factor()
let product = factor.create('hahah')
product.init()
product.fn1()
- 应用场景
- jQuery中$('div'), jQuery库的封装实现基于工厂模式
class jQuery{ constructor(selector){} append(){} addClass(){} html(){} } Window.$ = function(selector){ return new jQuery(selector) }
- React.createElement
class Vnode{ constructor(tags, attrs, children){ //省略内部实现代码 } } React.createElement = function(tags, attrs, children){ return new Vnode(tags, attrs, children) }
- vue异步组件
Vue.component('example-component', ()=>{ setTimeout(()=>{ resolve({ template: '<div>hello</div>' }) }, 1000) })
- 阅读经典lib源码的意义
- 学习如何实现功能
- 学习设计思路
- 强制自己写代码,最后写出更好的代码
- 先拿来主义,消化吸收后,再去创新
- 设计原则验证
- 构造函数与创建者分离,即产品与工厂分离
- 符合开放封闭原则,即通过工厂方法将构造函数与用户隔离,使他们之间不产生耦合关系
# 单例模式
- 特点
- 系统中被唯一使用
- 一个类只能初始化一个实例
- 示例
- 登录框
- 购物车
- 单例模式的实现思路
- 如果有了,就直接用,如果没有,就实例化一个,但始终保证这个实例是系统中被唯一使用的
- 代码演示
- 利用Symbol实现node模块的单例模式
const FOO_KEY = Symbol.for('foo')
function A(){
this.foo = 'hello'
}
if(!global[FOO_KEY]){
global[FOO_KEY] = new A()
}
module.exports = global[FOO_KEY]
- Singleton 模式指的是调用一个类,任何时候返回的都是同一个实例
class SingleObject{
login(){
console.log('login......')
}
}
SingleObject.getInstance = (() => {
let instance
return function(){
if(!instance){
instance = new SingleObject()
}
return instance
}
})()
// 注意:这里只能使用静态方法SingleObject.getInstance()生成单例,而不能使用new SingleObject()
let obj1 = SingleObject.getInstance()
obj1.login()
let obj2 = SingleObject.getInstance()
obj2.login()
console.log(obj1===obj2) //true obj1与obj2是同一单例,完全相等
let obj3 = new SingleObject()
console.log(obj1===obj3) //false
- 应用场景
- jQuery中只有一个'$'
if(window.jQuery!=null){ return window.jQuery }else{ //实例化一个 }
- 模拟登录框
class loginForm{ constructor(){ this.state = 'hide' } show(){ if(this.state === 'show'){ console.log('已显示') return } this.state = 'show' console.log('登录框显示成功') } hide(){ if(this.state === 'hide'){ console.log('已隐藏') return } this.state = 'hide' console.log('登录框隐藏成功') } } loginForm.getInstance=(()=>{ let instance return function(){ if(!instance){ instance = new loginForm() } return instance } })() let loginForm1 = loginForm.getInstance() loginForm1.show() //登录框显示成功 let loginForm2 = loginForm.getInstance() loginForm2.show() //已显示,因为loginForm1与loginForm2是同一个登录框 console.log(loginForm1===loginForm2)
- 购物车
- vuex和redux中的store
- 设计原则验证
- 符合单一指责原则,只实例化唯一的对象
- 没法具体符合开放封闭原则,但绝对不违反开放封闭原则
# 观察者模式
- 前端应用最多的一种设计模式
- 特点:
- 发布 & 订阅
- 一对多,当然也可以一对一
- 订阅某个主题,当主题发生变化时,通知所有的观察者去执行相应的操作
- 代码演示·
// 保存状态,状态变化之后触发所有观察者对象
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} updated, state: ${this.subject.getState()}`)
}
}
// 测试
let s = new Subject()
let o1 = new Observer('o1', s)
let o2 = new Observer('o2', s)
s.setState(1)
// o1 updated, state: 1
// o2 updated, state: 1
- 应用场景
- 网页事件绑定,所有的事件监听机制
- Promise, .then(() =>{})
- jQuery callbacks
var callbacks = $.Callbacks() //这是jQuery比较底层的一个api callbacks.add(function(info){ //注册监听回调 console.log('fn1', info) }) callbacks.add(function(info){ console.log('fn2', info) }) callbacks.fire('gogogo') //触发 callbacks.fire('haahah')
- nodejs 自定义事件
- nodejs 处理http请求;多进程通信
- Vue,React中生命周期函数触发(发布订阅)
- vue的watch
- 设计原则验证
- 主题与观察者分离,不是主动触发而是被动监听,两者解耦
- 符合开放封闭原则