Adapter Pattern with JavaScript
Walther Carrasco
Posted on January 26, 2021
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.
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:
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!
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:
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.
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.
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. 🔥
Posted on January 26, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.