怎样将对象组合起来, 并规定这些对象之间的交流方式, 使其易扩展, 复用, 适配
Strategy 策略模式
将某对象逻辑里面可能发生变化的部分单独抽出来, 这部分可用各种策略
来实现, 不同的策略, 该对象表现不同的行为
比如: 汽车换轮胎
-
平常: 使用普通轮胎,
-
雪天: 使用雪地轮胎
我们不需要仅仅因为换轮胎, 就把整个车都换掉
// Car 中轮胎是可能发生变化的部分, 将其单独抽出来
class Car {
constructor(trie) {
this.tire = trie
}
getTire() {
return this.tire
}
}
// 根据不同的天气, 得到不同的轮胎
class Tire {
constructor(weather) {
this.weather = weather
}
getNormalTire() {
return 'normalTire'
}
getSnowTire() {
return 'snowTire'
}
getTire() {
const weatherNeedTire = {
normal: this.getNormalTire,
snow: this.getSnowTire,
}
return weatherNeedTire[this.weather]() // 匹配需要的天气, 才会运行 getXXXTire 方法, 懒加载
}
}
function main() {
const normalTire = new Tire('normal').getTire()
const normalCar = new Car(normalTire)
console.log(normalCar.getTire())
const snowTire = new Tire('snow').getTire()
const snowCar = new Car(snowTire)
console.log(snowCar.getTire())
}
main()
State 状态模式
不同的状态, 表现出与该状态相对应的行为
State 为 Strategy 的特例: 举个夸张😏 的比方, 还是上面汽车轮胎的例子, 假设车子的状态会发生变化
- 当车子为
普通车
, 轮子为普通轮子
- 当车子为
雪地车
, 轮子为雪地轮子
另一个例子: 构建一个服务器, 接受客户端发送的数据, 并打印出来
server.js
import jsonOverTcp from 'json-over-tcp-2'
const server = jsonOverTcp.createServer({ port: 5000 })
server.on('connection', socket => {
socket.on('data', data => {
console.log('Client data', data)
})
})
server.listen(5000, () => console.log('Server started'))
客户端: 每隔 1 秒制造一条数据, 并调用 send 函数
, send 函数
在服务器在线和离线时, 表现出不同的行为
服务器在线
的时候: 将数据存入 queue 中, 并读取 queue 中的数据, 将其发送给服务器, 并将 queue 中的数据 pop 出来服务器离线
的时候: 将数据存入 queue 中
初始认为服务器离线, 状态转移时, 执行 active 函数, 其行为如下
离线 => 在线: 读取 queue 中所有数据, 递归将其发送给服务器, 并将其 pop 出来
在线 => 离线: 每隔 1秒, 尝试连接服务器

client.js
import { FailsafeSocket } from './failsafeSocket.js'
const failsafeSocket = new FailsafeSocket({ port: 5000 })
setInterval(() => {
// send current memory usage
failsafeSocket.send(process.memoryUsage())
}, 1000)
failsafeSocket.js 初始状态为离线
import { OfflineState } from './offlineState.js'
import { OnlineState } from './onlineState.js'
export class FailsafeSocket {
constructor (options) {
this.options = options
this.queue = []
this.currentState = null
this.socket = null
this.states = {
offline: new OfflineState(this),
online: new OnlineState(this)
}
this.changeState('offline')
}
changeState (state) {
console.log(`Activating state: ${state}`)
this.currentState = this.states[state]
this.currentState.activate()
}
send (data) {
this.currentState.send(data)
}
}
offlineState.js
import jsonOverTcp from 'json-over-tcp-2'
export class OfflineState {
constructor (failsafeSocket) {
this.failsafeSocket = failsafeSocket
}
send (data) {
this.failsafeSocket.queue.push(data)
}
activate () {
const retry = () => {
setTimeout(() => this.activate(), 1000)
}
console.log('Trying to connect...')
this.failsafeSocket.socket = jsonOverTcp.connect(
this.failsafeSocket.options,
() => {
console.log('Connection established')
this.failsafeSocket.socket.removeListener('error', retry)
this.failsafeSocket.changeState('online')
}
)
this.failsafeSocket.socket.once('error', retry)
}
}
onlineState.js
export class OnlineState {
constructor (failsafeSocket) {
this.failsafeSocket = failsafeSocket
this.hasDisconnected = false
}
send (data) {
this.failsafeSocket.queue.push(data)
this._safeWrite(data)
}
_safeWrite (data) {
this.failsafeSocket.socket.write(data, (err) => {
if (!this.hasDisconnected && !err) {
this.failsafeSocket.queue.shift()
}
})
}
activate () {
this.hasDisconnected = false
for (const data of this.failsafeSocket.queue) {
this._safeWrite(data)
}
this.failsafeSocket.socket.once('error', () => {
this.hasDisconnected = true
this.failsafeSocket.changeState('offline')
})
}
}
Template 模板模式
定义一个抽象类, 用来实现某个组件的裤架, 并留下一些还未实现的步骤, 让子类去做, 这样的步骤称为模板方法
(类似 Java 中的接口)
class Car {
constructor(trie) {
this.tire = trie
}
getTire() {
return this.tire
}
}
class TireTemplate {
getNormalTire() {
throw new Error('getNormalTire() must be implemented')
}
getSnowTire() {
throw new Error('getSnowTire() must be implemented')
}
getTire() {
throw new Error('getTire() must be implemented')
}
}
class Tire extends TireTemplate {
constructor(weather) {
super()
this.weather = weather
}
getNormalTire() {
return 'normalTire'
}
getSnowTire() {
return 'snowTire'
}
getTire() {
const weatherNeedTire = {
normal: this.getNormalTire,
snow: this.getSnowTire,
}
return weatherNeedTire[this.weather]()
}
}
function main() {
const normalTire = new Tire('normal').getTire()
const normalCar = new Car(normalTire)
console.log(normalCar.getTire())
const snowTire = new Tire('snow').getTire()
const snowCar = new Car(snowTire)
console.log(snowCar.getTire())
}
main()
Middleware 中间件模式
企业中的 Middleware 指: 底层机制的抽象
Nodejs 中的 Middleware 指: 底层服务
与应用程序
之间起到粘合作用的软件层
(位于两者中间的软件)
代表: express
在这里, 中间件是一套服务
, 这些服务形成一条管道, 用以处理服务器收到的 http 请求
, 并负责给出相关的响应
var express = require('express')
var app = express()
const middleware = (req, res, next) => {
// TODO SOMETHING
next()
}
app.use(middleware )
app.use(middleware)
app.use(middleware)
app.listen(3000)
关于 next
的作用, 可以看看这篇文章: koa 洋葱模型的简单实现
Command 命令模式
将执行某动作所需要的信息
用一个对象封装起来, 以便稍后加以执行, 封装的对象称为command 对象
使用 Task 模式实现 Command 模式
// target 为要调用的操作
function createTask(target, ...args) {
// 这种闭包又叫做 target 的 bound function (绑定函数)
const closure = () => {
target(...args)
}
return closure
}
const foo = a => console.log(a)
// 封装的对象, 也称为 command 对象
const task = createTask(foo, 123)
task()
// task 写法与如下写法类似
const task2 = foo.bind(null, 123)
task2()