Adapter Pattern with JavaScript
Tags: adapter, pattern, javascript, designpattern
Published: 2021-01-26 10:51:59

Hello devs!

Today I challenged myself to write my first post and I wanted to be about the Adapter Design Pattern.

**Design patterns** are the basis of all good software. A design pattern is a general solution to a reappearing problem.

Now, what is **Adapter Pattern**? If we bring the problem from the real domestic world, a adapter is used to connect two or more things which can't be connected with their original sockets.

An example of this is with the new cellphones. Normally most of the phones have a universal port (3.5mm) for headphones. So their connection is made directly.
With the new cellphones, the companies decided to remove the headphone port, leaving only the charging port.

Here is where the adapter comes into play. Companies made an adapter so you can still use the 3.5mm headphones using the charging port.

Now that we understand better what is the Adaptor Pattern, I present you a JavaScript example.

Imagine that we decided to create a **Calculator**. This calculator needs three attributes (num1, num2, operation), the last one is in charge of the operation that will be realized.

```javascript
class Calculator {
  operation(num1, num2, operation) {
    switch (operation) {
      case 'multiplication':
        return num1 * num2;
      case 'division':
        return num1 / num2;
      default:
        return NaN;
    }
  }
}

export default Calculator;
```

and we can use the class like this:
```javascript
import Calculator from "./Calculator"

const calculator = new Calculator();
const multi = calculator.operation(1, 2, 'multiplication');
console.log(multi ); //output 2

const div = calculator.operation(10, 2, 'division');
console.log(div); //output 5
```

The time passes and the project gets bigger and bigger. It's time for a **complete refactor** of the Calculator class!

```javascript
class Calculator {
  add(num1, num2) {
    return num1 + num2;
  }
  div(num1, num2) {
    return num1 / num2;
  }
  mult(num1, num2) {
    return num1 * num2;
  }
}

export default Calculator;
```

This is the new way of using the calculator:
```javascript
import Calculator from "./Calculator"

const calculator = new Calculator();
const sum = calculator.add(1, 2);
console.log(sum); //output 3

const sub = calculator.div(10, 2);
console.log(sub); //output 5
```

As we can see, the refactor is no more compatible with the last version. For this we need to create an **adaptor** to make it work with both versions.

```javascript
import Calculator from "./Calculator";

class CalculatorAdapter {
  constructor() {
    this.calculator = new Calculator();
  }
  operation(num1, num2, operation) {
    switch (operation) {
      case "add":
        return this.calculator.add(num1, num2);
      case "multiplication":
        return this.calculator.mult(num1, num2);
      case "division":
        return this.calculator.div(num1, num2);
      default:
        return NaN;
    }
  }
}

export default CalculatorAdapter;
```

Now we can use the the original Calculator with the Adapter.
```javascript
import Calculator from "./Calculator";
import CalculatorAdapter from "./CalculatorAdapter";

//Adapter
const calcAdapter = new CalculatorAdapter();
const sumAdapter = calcAdapter.operation(2, 2, "multiplication");
console.log(sumAdapter); //output 4

//Calculator
const calculator = new Calculator();
const sum = calculator.mult(2, 2);
console.log(sum); //output 4
```


What are the pros and cons of this pattern?
**Pros**
- It works with **SOLID** principles
- We can add new adapters without braking the existing code.

**Cons**
- The complexity of the code increases. This due the necessity of introducing new interfaces and classes.

Thanks for reading! Feel free to leave your feedback and love.

Have a great time and see you in future posts. 🔥