Adapter Pattern
Published: 2020-03-17 21:23:22

___
### Structural Design Pattern

Github link: https://github.com/FrancescoXX/Design-Pattern-Adapter-Javascript

___

## 📌Introduction
The Adapter pattern is used to allow a new use of an existing interface of a class, with a new interface, using the same methods.
We separate the code well (Single responsibility principle).
We dont need to change the existing class (open/closed principle).
___

## ⚡️In short
We have:
Target: Interface the client uses.
Adapter: Transforms the request of the client to a specific request.
Adapteee: Class we want to adapt.
___


## 💡Intent
- Wrap an existing class with a new interface.
- Convert an interface into another one.
- Let classes work together that couldn't otherwise because of incompatible interfaces.

___


## 🔧 Apply when (we want to)
- Re-use an existing class, but the interface is not compatible
- Combine unrelated classes with an incompatible interface

___

## ✅Pro
- Single Responsibility Principle: We can separate the different interfaces' logic.
- Open/Closed Principle. We can introduce new adapters without breaking the existing code.

___


## ⚠️Cons
- How much adapting does the adapter do? Complex adaptations could be be hard to write
- The overall complexity of the code increases 
- We need to introduce new interfaces and classes. 
- Sometimes it’s better to change the class. (Not always possible by the way).

___


## 🏆 Great for
- Connect to legacy systems
- Adapt one interface to another

___

```javascript
/** Adapter Design pattern
 *  
 *  Structural Design Pattern
 */

//Target
class LegacyShopper {
  constructor() {
    this.request = (product, quantity, price) => `${price * quantity}$`;
  }
}

// Adapteee
class OnlineShopping {
  constructor() {
    this.authenticate = (username, password) => console.log(`login logic for...${username} // ${password}`);
    this.setProduct = (product) => console.log(`setting product to ${product}`);
    this.setQuantity = (quantity) => console.log(`setting quantity to ${quantity}`);
    this.applyDiscount = (price) => price * 0.9; // online discount
    this.checkout = (quantity, price) => `${(this.applyDiscount(price)) * quantity}$`;
  }
}

// Adapter interface
class Adapter {
  constructor(username, password) {
    const cart = new OnlineShopping();
    cart.authenticate(username, password);

    this.request = (product, quantity, price) => {
      cart.setProduct(product);
      cart.setQuantity(quantity);
      return cart.checkout(quantity, price);
    }
  };
}

// legacy shopping
const cart = new LegacyShopper();
console.log("***Legacy system***");
console.log("Standard cost: " + cart.request("apples", 10, 3));

// OUTPUT
//
//***Legacy system***
//Standard cost: 30$

//////////////////////////////////////////////////////////////

// new shopping with Adapted interface
console.log("\n***New system***");

const adapter = new Adapter("Francesco", "123456"); //login logic simulation
//Same request, using the adapter
console.log("Online cost: " + adapter.request("apples", 10, 3)); //27$

// OUTPUT:
//
// ***New system***
// login logic for...Francesco // 123456
// setting product to apples
// setting quantity to 10
// Online cost: 27$
```





Github link: https://github.com/FrancescoXX/Design-Pattern-Adapter-Javascript