JavaScript Design Patterns — Adapters and Facades
Tags: webdev, programming, javascript, architecture
Published: 2021-01-30 21:28:19

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


Design patterns are the basis of any good software. JavaScript programs are no exception.

In this article, we’ll look at the adapter and facade patterns.

### Adapter

The adapter pattern is useful for creating a consistent interface for another object.

The object we’re creating an interface for doesn’t fit with how it’s used.

Therefore, we create an adapter so that we can use them easily.

It also hides the implementation so that we can use it easily and with low coupling.

For instance, we can create an adapter object as follows:

```
const backEnd = {
  setAttribute(key, value) {
    //.,,
  },
  getAttribute() {
    //...
  }
}

const personAdapter = {
  setFirstName(name) {
    backEnd.setAttribute('firstName', name);
  },
  setLastName(name) {
    backEnd.setAttribute('lastName', name);
  },
  getFirstName() {
    backEnd.getAttribute('firstName');
  },
  getLastName() {
    backEnd.getAttribute('lastName');
  }
}
```

We created an adapter object called `personAdapter` so that we can use `backEnd` to set all the attributes.

The adapter has an interface that people can understand more easily since the method names are explicit.

Other objects or classes can use the object to manipulate the attributes.

We can use adapters to create interfaces that we want to expose to the public any way we want.

### Inheriting Objects with Adapters

With adapters, we can also create an interface for multiple classes or objects.

For instance, we can write:

```
const backEnd = {
  setAttribute(key, value) {
    //.,,
  },
  getAttribute() {
    //...
  }
}

const parentAdapter = {
  //...
  getAdapterName() {
    //...
  }
}

const personAdapter = Object.create(parentAdapter);

personAdapter.setFirstName = (name) => {
  backEnd.setAttribute('firstName', name);
};

personAdapter.setLastName = (name) => {
  backEnd.setAttribute('lastName', name);
};

personAdapter.getFirstName = () => {
  backEnd.getAttribute('firstName');
};

personAdapter.getLastName = () => {
  backEnd.getAttribute('lastName');
}
```

In the code above, we created `personAdapter` with `Object.create` , which allows us to inherit from another parent object.

So we get the `getAdapterName` method from the `parentAdapter` prototype object.

Then we add our own methods to `personAdapter` .

Now we can get inherited methods from another object plus the methods in our own adapter object in the adapter.

Likewise, we can do the same with the class syntax.

For instance, we can create an adapter class instead of an object.

We can write:

```
const backEnd = {
  setAttribute(key, value) {
    //.,,
  },
  getAttribute() {
    //...
  }
}

class ParentAdapter {
  //...
  getAdapterName() {
    //...
  }
}

class PersonAdapter extends ParentAdapter {
  setFirstName(name) {
    backEnd.setAttribute('firstName', name);
  }

  setLastName(name) {
    backEnd.setAttribute('lastName', name);
  }

  getFirstName() {
    backEnd.getAttribute('firstName');
  }

  getLastName() {
    backEnd.getAttribute('lastName');
  }

}

const personAdapter = new PersonAdapter();
console.log(personAdapter);
```

The code above has a `PersonAdapter` and `ParentAdapter` classes instead of objects.

We used the `extends` keyword to inherit members from `ParentAdapter` .

This is another way we can inherit members from a parent entity.

### Facade Pattern

We can use the facade pattern to create a class or object to hide the implementation of something complex behind it.

This is used to create an easy to use interface for the outside while keeping the complex implementation of something inside.

For instance, we can write:

```
const complexProduct = {
  setShortName(name) {
    //...
  },

  setLongName(name) {
    //...
  },

  setPrice(price) {
    //...
  },

  setDiscount(discount) {
    //...
  },
  //...
}

const productFacade = {
  setName(type, name) {
    if (type === 'shortName') {
      complexProduct.setShortName(name);
    } else if (type === 'longName') {
      complexProduct.setLongName(name);
    }
  }
  //...
}
```

We created a `productFacade` that has some methods that call various methods in the `complexProduct` object.

This way, we can use the facade to simplify what we do, and also reduce the coupling to the `complexProduct` object.

We let the `productFacade` object communicates with the `complexProduct` object.

It also serves to reduce coupling from complex objects.

In addition, a facade can also create an interface for something that won't change as often as what’s behind it.

An interface that doesn’t change as often is good since more changes mean more risks of bugs.

Likewise, we can create a facade class that does the same thing as follows:

```
const complexProduct = {
  setShortName(name) {
    //...
  },

  setLongName(name) {
    //...
  },

  setPrice(price) {
    //...
  },

  setDiscount(discount) {
    //...
  },
  //...
}

class ProductFacade {
  setName(type, name) {
    if (type === 'shortName') {
      complexProduct.setShortName(name);
    } else if (type === 'longName') {
      complexProduct.setLongName(name);
    }
  }
  //...
}
```

Then we can create an instance of `ProductFacade` instead of using the object literal directly.

A facade can be used to manipulate one or more objects. That’s different from the adapter pattern, where we make an adapter for one object.

### Conclusion

We can use the adapter pattern to hide the implementation of one object bu creating an interface that’s easier to work with to the outside.

The facade pattern lets us hide complex implementations behind one interface that can be used instead of one or more complex objects being the facade.