Adapter Pattern

适配器模式的实现与应用场景

问题

什么是适配器模式?如何在 JavaScript 中实现适配器模式?

解答

适配器模式用于将一个接口转换成另一个接口,使原本不兼容的类可以一起工作。就像电源适配器将不同规格的插头转换成统一接口。

基本实现

// 旧的 API 接口
class OldApi {
  getUsers() {
    return [
      { name: 'Alice', age: 25 },
      { name: 'Bob', age: 30 }
    ]
  }
}

// 新系统期望的接口格式
// { users: [{ username: string, userAge: number }] }

// 适配器:将旧 API 转换为新格式
class ApiAdapter {
  constructor(oldApi) {
    this.oldApi = oldApi
  }

  // 转换为新系统期望的格式
  fetchUsers() {
    const oldData = this.oldApi.getUsers()
    return {
      users: oldData.map(user => ({
        username: user.name,
        userAge: user.age
      }))
    }
  }
}

// 使用
const oldApi = new OldApi()
const adapter = new ApiAdapter(oldApi)
console.log(adapter.fetchUsers())
// { users: [{ username: 'Alice', userAge: 25 }, { username: 'Bob', userAge: 30 }] }

实际场景:统一多个第三方库

// 不同的日志库有不同的 API
class ConsoleLogger {
  log(message) {
    console.log(`[Console] ${message}`)
  }
}

class FileLogger {
  writeLog(msg, level) {
    console.log(`[File][${level}] ${msg}`)
  }
}

class RemoteLogger {
  send(data) {
    console.log(`[Remote] ${JSON.stringify(data)}`)
  }
}

// 统一的日志适配器接口
class LoggerAdapter {
  constructor(logger, type) {
    this.logger = logger
    this.type = type
  }

  // 统一的日志方法
  info(message) {
    switch (this.type) {
      case 'console':
        this.logger.log(message)
        break
      case 'file':
        this.logger.writeLog(message, 'INFO')
        break
      case 'remote':
        this.logger.send({ level: 'info', message })
        break
    }
  }
}

// 使用统一接口
const cons