Design Patterns in JavaScript — Part 4: The Adapter Pattern
Sachin Kasana

Sachin Kasana @sachinkasana

About: Principal Engineer by day, DevTools builder by night 🌙 | Love working with Node.js, React & AI | Sharing insights on clean code, performance, and web development. https://json-formatter-dev.vercel.ap

Location:
india
Joined:
Jun 30, 2022

Design Patterns in JavaScript — Part 4: The Adapter Pattern

Publish Date: Apr 27
0 0

Originally published on Medium, sharing here for the DEV community!

Design Patterns in JavaScript — Part 4: The Adapter Pattern

“Make it fit. Make it work. Don’t break the existing code.”

You’ve probably been here:

You integrate a third-party API…

…but its response format doesn’t match your frontend.

Now you’re stuck either rewriting your app logic or creating yet another hacky **.map() transformer**.

This is where the Adapter Pattern shines.

Let’s unpack how to use it cleanly — in the real world, not just textbook diagrams.

🧠 What Is the Adapter Pattern?

The Adapter Pattern lets you convert one interface into another  — so your system can talk to external or legacy code without knowing the difference_._

It’s like a power plug converter:

Different shape, same electricity ⚡

🔧 Use Case: Wrapping a Third-Party API Response

Imagine you’re consuming a product API like this:

{
  "product_name": "Laptop",
  "product_price": 2000,
  "product_desc": "High-end machine"
}
Enter fullscreen mode Exit fullscreen mode

But your frontend expects:

{
  name: "Laptop",
  price: 2000,
  description: "High-end machine"
}
Enter fullscreen mode Exit fullscreen mode

Instead of modifying every place in your code where this is used, you build an adapter:

✨ The Adapter

function adaptProductResponse(apiData) {
  return {
    name: apiData.product_name,
    price: apiData.product_price,
    description: apiData.product_desc,
  };
}
Enter fullscreen mode Exit fullscreen mode

Now use this in your fetch logic:

const apiResponse = await fetchProduct();
const product = adaptProductResponse(apiResponse);
Enter fullscreen mode Exit fullscreen mode

✅ Clean

✅ Centralized

✅ Reusable

🧪 Real Project Examples

Design pattern use cases

Use CaseAdapter Role3rd-party payment SDKs (Stripe, Razorpay)Wrap inconsistent APIs with one internal formatLegacy APIs with snake_case keysTransform to camelCaseFile upload formats (CSV → JSON)Normalize to internal schemaLogging frameworksNormalize log shape + metaUI componentsAdapter between form states and external libraries

📦 Advanced Example: Adapter for Notification Providers

class EmailProvider {
  sendEmail(to, message) {
    console.log(`Email to ${to}: ${message}`);
  }
}

class SlackAdapter {
  constructor(slackAPI) {
    this.slackAPI = slackAPI;
  }

  sendEmail(to, message) {
    this.slackAPI.sendMessage({ channel: to, text: message });
  }
}
Enter fullscreen mode Exit fullscreen mode

Now both can be used in the same way:

function notifyUser(provider, to, msg) {
  provider.sendEmail(to, msg);
}

notifyUser(new EmailProvider(), 'john@example.com', 'Hello!');
notifyUser(new SlackAdapter(slackAPI), '#alerts', 'New issue!');
Enter fullscreen mode Exit fullscreen mode

🧠 TL;DR

Use case of design pattern

🚀 What’s Next?

In the final part of this series, we’ll cover the State Pattern  — perfect for UI toggles, tab switching, step forms, and feature flags.

Want to turn boolean chaos into clean, readable state machines?

👉 Stay tuned here or follow on Medium — the series wraps soon!

Comments 0 total

    Add comment