Skip to content

The adapter pattern ​

Purpose ​

The adapter pattern allows us to create a new interface around an existing class. This is useful when a class has the behaviours we need, but they're implemented in a way that isn't compatible with the rest of our software.

For example, we might have legacy code for older smart lights:

js
class OldLight {
  constructor() {
    this.power = 1
  }

  on() {
    this.power = 1
  }

  off() {
    this.power = 0
  }
}

Using the adapter pattern, we can wrap this old code in an adapter so that we expose an isOn property and a togglePower() method, bringing it in line with the newer SmartLight class.

Implementation ​

We create an adapter class which accepts an instance of OldLight, and interacts with this instance to replicate the newer SmartLight interface.

js
class LightAdapter {
  #oldLight
  constructor(oldLight) {
    oldLight.off() // make sure it's off by default
    this.#oldLight = oldLight
  }

  get isOn() {
    return this.#oldLight.power === 1
  }

  togglePower() {
    if (this.isOn) {
      this.#oldLight.off()
    } else {
      this.#oldLight.on()
    }
  }
}

Now, we can wrap an old light in the adapter so that its interface is identical to a smart light.

js
const oldLight = new OldLight()
const adaptedLight = new LightAdapter(oldLight)

console.log(adaptedLight.isOn) // false
adaptedLight.togglePower()
console.log(adaptedLight.isOn) // true