共计 1399 个字符,预计需要花费 4 分钟才能阅读完成。
模式是什么
设计模式是:在软件设计过程中针对「特定」问题的「简洁而优雅」的解决方案。
在软件开发的历史中,沉淀了一些好的软件设计,而设计模式便是给这些好设计取了个名字。「好的设计」并不是某人发明的。一个稍有经验的程序员也许在不知不觉中数次使用过这些设计模式。
模式的意义
设计模式的意义是让人们写出可复用和可维护性高的程序。
举个例子,假设有一个空房间,我们要日复一日地往里面放一些东西。最简单的办法当然是把这些东西直接扔进去,但是时间久了,就会发现很难从这个房子里找到自己想要的东西,要调整某几样东西的位置也不容易。
所以在房间里做一些柜子也许是个更好的选择,虽然柜子会增加我们的成本,但它可以在维护阶段为我们带来好处。使用这些柜子存放东西的规则,或许就是一种模式。
所有设计模式的实现都遵循一条原则,即「找出程序中变化的地方,并将变化封装起来」。
一个程序的设计总是可以分为可变的部分和不变的部分。当我们找出可变的部分,并且把这些部分封装起来,那么剩下的就是不变和稳定的部分。这些不变和稳定的部分是非常容易复用的。
熟悉这些模式的程序员,对某些模式的理解也形成了条件反射,当合适的场景出现时,他们可以很快地找到某种模式作为解决方案。
我们主要学习以下模式:
单例模式
策略模式
代理模式
发布订阅模式
命令模式
状态模式
单例模式
单例模式的定义是:「保证仅有一个实例,并提供一个访问它的全局访问点」。
单列模式场景
单例模式是一种常用的模式,有一些对象我们往往只需要一个,比如全局缓存、浏览器中的 window 对象等。
举个前端的例子,网页 loading 图(菊花图)。页面整个生命周期,我们只需要生成一个 loading 就好了。既简化了逻辑 (不必去考虑多个请求打开了多个 loading) 又减少了 dom 的创建。
实现单例
在 javascript 中,函数是一等公民,所以例子我都优先使用函数来实现(原书是以面向对象的形式展现)
function generateInstance() {
return {
say() {
console.log(‘hello’)
}
}
}
let single = (function() {
let instance // 哨兵变量
return function getSingle() {
if (!instance) {
// 如果还没有生成实例,那么生成一个。
instance = generateInstance()
}
return instance
}
})()
let a = single()
let b = single()
console.log(a === b) // true
以上就是一个单例的例子了。
我们利用闭包保存了一个哨兵变量,用来判断单例是否生成。
单例模式的优缺点
优点:
应用周期,只需实例化一次,对于生成实例开销大的情况,可以提高性能。
方便管理,确保的所有的引用都是同一个实例。
缺点:
实例储存在闭包,是无法销毁的。
范式
下面是一个生成单例的高阶函数。
var getSingle = function(fn) {
var result
return function() {
return result || (result = fn.apply(this, arguments))
}
}
// 用法
let singeName = getSingle(() => `hello ${Math.random()}`)
let a = singeName()
let b = singeName()
console.log(a === b) // true