JavaScript中设计模式的应用场景
JavaScript设计模式是解决特定问题的模板,它们提供了可复用的解决方案。理解这些模式的应用场景能提升代码的可维护性和扩展性。
单例模式的应用场景
单例模式确保一个类只有一个实例,并提供一个全局访问点。在JavaScript中,单例常用于管理全局状态或共享资源。
典型应用场景包括:
- 全局配置对象
- 缓存系统
- 日志系统
- 数据库连接池
class DatabaseConnection {
constructor() {
if (DatabaseConnection.instance) {
return DatabaseConnection.instance
}
this.connection = this.createConnection()
DatabaseConnection.instance = this
}
createConnection() {
// 创建数据库连接逻辑
return { status: 'connected' }
}
}
const db1 = new DatabaseConnection()
const db2 = new DatabaseConnection()
console.log(db1 === db2) // true
观察者模式的应用场景
观察者模式定义对象间的一对多依赖关系,当一个对象状态改变时,所有依赖它的对象都会得到通知。这种模式特别适合实现事件处理系统。
常见应用场景:
- DOM事件监听
- 数据绑定系统
- 自定义事件系统
- 状态管理库(如Redux)
class EventEmitter {
constructor() {
this.events = {}
}
on(event, listener) {
if (!this.events[event]) {
this.events[event] = []
}
this.events[event].push(listener)
}
emit(event, ...args) {
if (this.events[event]) {
this.events[event].forEach(listener => listener(...args))
}
}
}
const emitter = new EventEmitter()
emitter.on('data', (data) => console.log('Received:', data))
emitter.emit('data', { id: 1, value: 'test' })
工厂模式的应用场景
工厂模式提供创建对象的接口,让子类决定实例化哪个类。在JavaScript中,工厂模式常用于创建复杂对象或需要统一创建逻辑的场景。
典型应用场景:
- UI组件库
- 跨平台对象创建
- 复杂对象构造
- 依赖解耦
class Button {
render() {
throw new Error('必须实现render方法')
}
}
class WindowsButton extends Button {
render() {
return '<button style="padding: 8px 16px">Windows风格按钮</button>'
}
}
class MacButton extends Button {
render() {
return '<button style="padding: 12px 24px; border-radius: 6px">Mac风格按钮</button>'
}
}
function createButton(os) {
switch (os) {
case 'windows':
return new WindowsButton()
case 'mac':
return new MacButton()
default:
throw new Error('不支持的操作系统')
}
}
const winBtn = createButton('windows')
console.log(winBtn.render())
策略模式的应用场景
策略模式定义一系列算法,把它们封装起来,并且使它们可以相互替换。这种模式让算法的变化独立于使用算法的客户。
常见应用场景:
- 表单验证规则
- 支付方式选择
- 排序算法切换
- 折扣计算策略
const strategies = {
isNonEmpty(value, errorMsg) {
if (value === '') {
return errorMsg
}
},
minLength(value, length, errorMsg) {
if (value.length < length) {
return errorMsg
}
},
isMobile(value, errorMsg) {
if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) {
return errorMsg
}
}
}
class Validator {
constructor() {
this.cache = []
}
add(value, rule, errorMsg) {
const ary = rule.split(':')
this.cache.push(() => {
const strategy = ary.shift()
ary.unshift(value)
ary.push(errorMsg)
return strategies[strategy].apply(null, ary)
})
}
validate() {
for (let i = 0; i < this.cache.length; i++) {
const msg = this.cache[i]()
if (msg) {
return msg
}
}
}
}
const validator = new Validator()
validator.add('13812345678', 'isMobile', '手机号码格式不正确')
validator.add('', 'isNonEmpty', '密码不能为空')
const errorMsg = validator.validate()
console.log(errorMsg) // 密码不能为空
装饰者模式的应用场景
装饰者模式动态地给对象添加额外职责,相比继承更加灵活。在JavaScript中,装饰者模式常用于功能扩展。
典型应用场景:
- 高阶组件
- 中间件系统
- 功能增强
- AOP编程
function withLogging(WrappedComponent) {
return class extends React.Component {
componentDidMount() {
console.log(`Component ${WrappedComponent.name} mounted`)
}
componentWillUnmount() {
console.log(`Component ${WrappedComponent.name} will unmount`)
}
render() {
return <WrappedComponent {...this.props} />
}
}
}
class MyComponent extends React.Component {
render() {
return <div>原始组件</div>
}
}
const EnhancedComponent = withLogging(MyComponent)
适配器模式的应用场景
适配器模式将一个接口转换成客户希望的另一个接口,使接口不兼容的类可以一起工作。在JavaScript中,适配器常用于接口转换。
常见应用场景:
- 第三方库适配
- API版本兼容
- 数据格式转换
- 新旧系统对接
// 旧版API
class OldAPI {
request() {
return { data: 'old format', status: 200 }
}
}
// 新版API需要的格式
class NewAPI {
fetch() {
return { result: 'new format', code: 200 }
}
}
// 适配器
class APIAdapter {
constructor(api) {
this.api = api
}
fetch() {
const result = this.api.request()
return {
result: result.data,
code: result.status
}
}
}
const oldAPI = new OldAPI()
const adapter = new APIAdapter(oldAPI)
console.log(adapter.fetch()) // { result: 'old format', code: 200 }
代理模式的应用场景
代理模式为其他对象提供一种代理以控制对这个对象的访问。在JavaScript中,代理模式常用于访问控制、延迟初始化等。
典型应用场景:
- 图片懒加载
- 缓存代理
- 访问控制
- ES6 Proxy应用
class RealImage {
constructor(filename) {
this.filename = filename
this.loadFromDisk()
}
loadFromDisk() {
console.log(`Loading ${this.filename}`)
}
display() {
console.log(`Displaying ${this.filename}`)
}
}
class ProxyImage {
constructor(filename) {
this.filename = filename
this.realImage = null
}
display() {
if (!this.realImage) {
this.realImage = new RealImage(this.filename)
}
this.realImage.display()
}
}
const image = new ProxyImage('test.jpg')
// 图片尚未加载
image.display() // 此时才会真正加载
状态模式的应用场景
状态模式允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。这种模式特别适合处理复杂的状态逻辑。
常见应用场景:
- 游戏角色状态
- 订单状态管理
- UI组件状态
- 工作流引擎
class TrafficLight {
constructor() {
this.states = [new RedLight(), new YellowLight(), new GreenLight()]
this.current = this.states[0]
}
change() {
const totalStates = this.states.length
let currentIndex = this.states.findIndex(light => light === this.current)
this.current = this.states[(currentIndex + 1) % totalStates]
}
sign() {
return this.current.sign()
}
}
class Light {
constructor(light) {
this.light = light
}
}
class RedLight extends Light {
constructor() {
super('red')
}
sign() {
return 'STOP'
}
}
class YellowLight extends Light {
constructor() {
super('yellow')
}
sign() {
return 'STEADY'
}
}
class GreenLight extends Light {
constructor() {
super('green')
}
sign() {
return 'GO'
}
}
const trafficLight = new TrafficLight()
console.log(trafficLight.sign()) // STOP
trafficLight.change()
console.log(trafficLight.sign()) // STEADY
trafficLight.change()
console.log(trafficLight.sign()) // GO
命令模式的应用场景
命令模式将请求封装为对象,从而允许使用不同的请求、队列或日志来参数化其他对象。这种模式特别适合实现撤销/重做功能。
典型应用场景:
- 撤销/重做操作
- 宏命令
- 任务队列
- 事务系统
class Calculator {
constructor() {
this.current = 0
this.history = []
}
execute(command) {
this.current = command.execute(this.current)
this.history.push(command)
}
undo() {
const command = this.history.pop()
this.current = command.undo(this.current)
}
getValue() {
return this.current
}
}
class AddCommand {
constructor(value) {
this.value = value
}
execute(current) {
return current + this.value
}
undo(current) {
return current - this.value
}
}
class MultiplyCommand {
constructor(value) {
this.value = value
}
execute(current) {
return current * this.value
}
undo(current) {
return current / this.value
}
}
const calculator = new Calculator()
calculator.execute(new AddCommand(10))
calculator.execute(new MultiplyCommand(2))
console.log(calculator.getValue()) // 20
calculator.undo()
console.log(calculator.getValue()) // 10
组合模式的应用场景
组合模式将对象组合成树形结构以表示"部分-整体"的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
常见应用场景:
- UI组件树
- 文件系统
- 组织结构图
- 菜单系统
class Component {
constructor(name) {
this.name = name
}
add(component) {
throw new Error('不支持的操作')
}
remove(component) {
throw new Error('不支持的操作')
}
display(depth) {
throw new Error('必须实现display方法')
}
}
class Leaf extends Component {
constructor(name) {
super(name)
}
display(depth) {
console.log(`${'-'.repeat(depth)}${this.name}`)
}
}
class Composite extends Component {
constructor(name) {
super(name)
this.children = []
}
add(component) {
this.children.push(component)
}
remove(component) {
const index = this.children.indexOf(component)
if (index !== -1) {
this.children.splice(index, 1)
}
}
display(depth) {
console.log(`${'-'.repeat(depth)}${this.name}`)
this.children.forEach(child => child.display(depth + 2))
}
}
const root = new Composite('root')
root.add(new Leaf('Leaf A'))
root.add(new Leaf('Leaf B'))
const comp = new Composite('Composite X')
comp.add(new Leaf('Leaf XA'))
comp.add(new Leaf('Leaf XB'))
root.add(comp)
root.display(1)
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:设计模式的定义与重要性