TypechoJoeTheme

至尊技术网

统计
登录
用户名
密码

JavaScript闭包实现策略模式:构建灵活可扩展的代码架构

2025-08-27
/
0 评论
/
1 阅读
/
正在检测是否收录...
08/27

JavaScript闭包实现策略模式:构建灵活可扩展的代码架构

策略模式的核心思想与闭包优势

策略模式(Strategy Pattern)是一种将算法封装在独立对象中的设计模式,允许客户端在运行时灵活切换算法实现。而JavaScript闭包(Closure)通过保留函数创建时的词法环境,为策略模式提供了天然的实现载体。

闭包实现策略模式的三大优势
1. 状态封装:闭包可以维持策略执行时的私有状态
2. 接口统一:所有策略对象保持相同的方法签名
3. 无污染全局:避免策略实现污染全局命名空间

基础实现:表单验证策略案例

javascript
// 策略容器
const validationStrategies = (function() {
// 私有策略集合
const strategies = {
isNonEmpty: function(value, errMsg) {
if(value === '') return errMsg
},
minLength: function(value, length, errMsg) {
if(value.length < length) return errMsg
},
isMobile: function(value, errMsg) {
if(!/^1[3-9]\d{9}$/.test(value)) return errMsg
}
}

return {
// 统一执行接口
validate: function(type, ...args) {
return strategies[type] && strategiestype
},
// 动态添加策略
addStrategy: function(name, fn) {
strategies[name] = fn
}
}
})()

// 使用示例
const errorMsg = validationStrategies.validate(
'isMobile',
'13812345678',
'手机号格式错误'
)

进阶应用:电商促销策略系统

javascript
function createPromotionStrategy() {
// 策略缓存
const strategies = new Map()

// 上下文状态
let currentStrategy = 'normal'
let history = []

// 注册策略
function register(name, strategyFn) {
strategies.set(name, strategyFn)
return this // 支持链式调用
}

// 执行当前策略
function execute(price) {
const result = strategies.has(currentStrategy)
? strategies.get(currentStrategy)(price)
: price

history.push({
  strategy: currentStrategy,
  input: price,
  output: result,
  timestamp: Date.now()
})

return result

}

// 切换策略
function useStrategy(name) {
if(strategies.has(name)) {
currentStrategy = name
}
return this
}

return {
register,
execute,
useStrategy,
getHistory: () => [...history],
getCurrentStrategy: () => currentStrategy
}
}

// 初始化策略系统
const promotion = createPromotionStrategy()
.register('discount', price => price * 0.8)
.register('fullReduce', price => price > 200 ? price - 50 : price)
.register('newUser', price => price * 0.5)

// 运行时动态切换策略
promotion.useStrategy('fullReduce')
console.log(promotion.execute(250)) // 输出200

性能优化与内存管理

  1. 策略缓存:使用WeakMap存储不常用的策略,避免内存泄漏
  2. 惰性加载:按需加载策略实现而非初始化时全部加载
  3. 策略复用:通过原型共享相同策略的多个实例

javascript
const advancedStrategy = (function() {
const coreStrategies = {
// 基础策略...
}

const lazyStrategies = new WeakMap()

function loadExternalStrategy(key) {
// 模拟异步加载
return import(./strategies/${key}.js)
.then(module => {
lazyStrategies.set(key, module.default)
return module.default
})
}

return {
async execute(key, ...args) {
if(coreStrategies[key]) {
return coreStrategieskey
}

  if(lazyStrategies.has(key)) {
    return lazyStrategies.get(key)(...args)
  }

  const strategy = await loadExternalStrategy(key)
  return strategy(...args)
}

}
})()

与模块系统的结合实践

在现代前端工程中,闭包策略模式可以与ES Modules完美结合:

javascript
// strategies/discount.js
let executionCount = 0

export default function discountStrategy(price, ratio = 0.9) {
executionCount++
console.log(折扣策略已执行${executionCount}次)
return price * ratio
}

// strategyContext.js
export function createStrategyContext() {
const strategies = new Map()

async function loadStrategy(modulePath) {
try {
const module = await import(modulePath)
strategies.set(module.name || modulePath, module.default)
} catch(e) {
console.error('策略加载失败:', e)
}
}

function getStrategy(name) {
return strategies.get(name)
}

return {
loadStrategy,
getStrategy
}
}

单元测试策略模式的最佳实践

javascript
describe('闭包策略模式测试套件', () => {
let strategySystem

beforeEach(() => {
strategySystem = createPromotionStrategy()
.register('double', n => n * 2)
.register('square', n => n * n)
})

test('应正确执行注册策略', () => {
strategySystem.useStrategy('double')
expect(strategySystem.execute(3)).toBe(6)

strategySystem.useStrategy('square')
expect(strategySystem.execute(3)).toBe(9)

})

test('应记录策略执行历史', () => {
strategySystem.useStrategy('double').execute(5)
strategySystem.useStrategy('square').execute(4)

const history = strategySystem.getHistory()
expect(history).toHaveLength(2)
expect(history[0].output).toBe(10)
expect(history[1].output).toBe(16)

})
})

浏览器环境下的应用场景

  1. 表单验证系统:根据字段类型动态切换验证规则
  2. 动画引擎:不同的缓动函数作为独立策略
  3. 请求处理:针对不同API版本采用不同的参数处理策略
  4. UI渲染:根据设备类型选择不同的布局策略

javascript
// 响应式布局策略示例
const layoutStrategies = (() => {
const strategies = {
mobile: () => {
document.body.classList.add('mobile-layout')
// 移动端特定逻辑...
},
desktop: () => {
document.body.classList.add('desktop-layout')
// 桌面端特定逻辑...
}
}

function detectDeviceType() {
return window.innerWidth < 768 ? 'mobile' : 'desktop'
}

return {
applyLayout() {
const type = detectDeviceType()
strategiestype
}
}
})()

// 监听窗口变化
window.addEventListener('resize', debounce(layoutStrategies.applyLayout, 300))

Node.js中的特殊应用场景

  1. 中间件处理:不同路由采用不同的认证策略
  2. 日志系统:根据环境切换日志记录策略
  3. 数据库访问:多数据源切换策略
  4. 文件处理:不同文件类型的解析策略

javascript
// 多数据库切换策略
function createDBStrategy(config) {
const drivers = new Map()
let currentDriver = 'mysql'

async function connect(name = currentDriver) {
if(!drivers.has(name)) {
const driver = require(./drivers/${name})
drivers.set(name, await driver.createConnection(config[name]))
}
currentDriver = name
return drivers.get(name)
}

return {
connect,
query(sql, params = []) {
return drivers.get(currentDriver).query(sql, params)
},
switchTo(name) {
if(drivers.has(name)) {
currentDriver = name
}
return this
}
}
}

// 使用示例
const db = createDBStrategy({
mysql: { /* 配置 / }, pg: { / 配置 */ }
})

await db.connect('pg').query('SELECT * FROM users')

朗读
赞(0)
版权属于:

至尊技术网

本文链接:

https://www.zzwws.cn/archives/36882/(转载时请注明本文出处及文章链接)

评论 (0)