标准答案
- 主程序要提供 use(plugin, options) 这类注册方法。
- 插件通常暴露 install(app, options) 或 apply(context) 方法。
- 上下文只暴露必要能力,例如注册命令、注册钩子、读取配置、扩展实例方法。
- 要避免同一个插件重复安装,可以用 Set 做去重。
- 复杂插件系统还要处理生命周期顺序、依赖关系、错误隔离和权限边界。
题目解析
插件机制解决的是扩展能力和核心稳定性的矛盾。核心代码不能为每个业务场景无限加分支,但也不能让外部代码随便改内部状态。
好的插件接口应该小而稳定。插件拿到的是受控上下文,只能通过公开方法注册能力。这样核心内部重构时,只要插件 API 不变,插件就不需要跟着改。
执行顺序和重复安装也要考虑。插件如果注册路由、指令、命令或生命周期钩子,顺序不同可能影响结果;重复安装则可能导致重复监听和重复副作用。
代码示例
下面是一个最小插件系统:支持安装去重、暴露上下文和注册钩子。
JavaScript
function createApp() {
const installedPlugins = new Set()
const hooks = new Map()
const app = {
use(plugin, options) {
if (installedPlugins.has(plugin)) {
return app
}
installedPlugins.add(plugin)
if (typeof plugin === 'function') {
plugin(app, options)
} else if (plugin && typeof plugin.install === 'function') {
plugin.install(app, options)
}
return app
},
hook(name, callback) {
const callbacks = hooks.get(name) || []
callbacks.push(callback)
hooks.set(name, callbacks)
},
emitHook(name, payload) {
const callbacks = hooks.get(name) || []
callbacks.forEach(callback => callback(payload))
}
}
return app
}常见误区
- 插件直接修改内部私有状态,导致核心实现无法重构。
- 没有安装去重,同一个插件重复注册事件或钩子。
- 没有定义清楚插件生命周期和执行顺序,多个插件互相影响时难以排查。