JavaScript 中的中介者模式
在 JavaScript 中,模块模式是一种广泛使用且功能强大的模式。它的实现极其简单,但它允许开发者封装代码,因此成为构建健壮代码最通用的模式之一。当你查看 JavaScript 库的源代码时,你很可能看到的就是这种模式的实现。此外,它们很可能也是单例对象——在应用程序的整个生命周期中,只有一个实例存在。
对于 JavaScript 新手来说,理解模块模式可能比较困难,因为它有很多不同的变体。然而,所有的时间和精力都是值得的,因为一旦你理解了这个概念,你就会发现编写大部分应用程序都会用到模块模式。
变体
立即调用函数表达式
模块模式中最流行的变体可以说是 IIFE(立即调用函数表达式)。这些函数本质上是立即执行的函数,并且应该返回一个对象(换句话说,一个接口),该对象将用作模块。
这些函数内部包含私有代码,这些代码只能在该函数的作用域内访问,除非返回的接口(外部可公开访问)提供了可以以某种方式访问它们的方法。
模块
正如你可能已经猜到的那样,模块模式允许你创建模块。
我们将使用立即执行函数表达式 (IIFE) 来实现我们自己的模块。这允许我们将 IIFE 的返回值直接赋给一个变量,以便我们可以像使用 JavaScript 模块一样使用它。
例如,假设我们正在开发一款角色扮演游戏,首先要做的是创建一个女巫类。女巫将拥有对目标造成伤害的方法。几乎所有角色扮演游戏中,女巫通常都会施放法术或魔法,因此我们将定义一个接口来模拟这一概念:
const sorceress = (function() {
const sideEffects = {
intervals: {},
}
function _fireBolt(target, customDamage) {
target.hp -= customDamage !== undefined ? customDamage : 15
}
function _thunderBolt(target) {
target.hp -= 15
}
function blizzard(target) {
target.hp -= 15
}
function _applyThunderBoltSideEffects(
target,
{ interval = 1000, timeout = 15000 } = {},
) {
if (sideEffects.intervals[target.id]) {
clearInterval(sideEffects.intervals[target.id])
}
sideEffects.intervals[target.id] = setInterval(() => {
target.hp -= 1
}, interval)
setTimeout(() => {
if (sideEffects.intervals[target.id]) {
clearInterval(sideEffects.intervals[target.id])
}
}, timeout)
}
return {
fireBolt(target, options) {
if (options) {
_fireBolt(target, options.customDamage)
} else {
_fireBolt(target)
}
},
thunderBolt(target) {
_thunderBolt(target)
_applyThunderBoltSideEffects(target)
},
blizzard,
}
})()
在这个例子中,我们的女巫类有三个方法:sorceress.fireBolt,,sorceress.thunderBolt和sorceress.blizzard。
在模块内部,我们声明了三个私有函数和一个公共函数。显然,以下划线开头的函数_是私有函数,其余的是公共函数。然而,我们并非通过这种方式来区分模块内部的公有和私有代码,而是通过闭包的返回值来区分。我们返回了一个对象,该对象对调用者可见。正是这种声明私有和公共变量的能力,使得模块模式成为 JavaScript 中最强大的模式之一。
通过保密,我们可以防止代码泄露给“外界”。
文章来源:https://dev.to/jsmanifest/the-mediator-pattern-in-javascript-3970