[Design Pattern] Ứng dụng Adapter Design Pattern trong dự án

0
Dịch vụ dạy kèm gia sư lập trình

Xin chào cả nhà,

Hôm nay là một ngày mà lương không về, mình ngồi suy nghĩ vẩn vơ và quyết định tiếp tục lên bài cho Series Design Patterns. Chủ đề là Adapter Design Pattern.

💥 Bài viết trước, các bạn tham khảo thêm: Factory Method Patterns

Design Pattern là một trong những nền tảng để có được một mã nguồn phần mềm tốt. Trong mã nguồn dự án, có những vấn đề mà nhiều dự án gặp phải, lúc này các “pháp sư” mới nghĩ ra các giải pháp tổng thể để giải quyết đó, đây chính là nguồn gốc và mục đích ra đời của một Design Pattern.

Vậy Adapter Design Pattern là gì? Nó sinh ra để giải quyết vấn đề gì? Khi nào thì nên sử dụng Adapter Pattern?

Chúng ta cùng tìm hiểu nhé.

Adapter Design Pattern là gì?

Như tên gọi của nó, Adapter có nghĩa là bộ chuyển đổi. Trong đời sống hằng ngày, chúng ta sử dụng rất nhiều Adapter.

Ví dụ, bạn vừa mới sắm một con iPhone 14 Pro max mới nhất, cổng tai nghe là Lightning. Nhưng đáng tiếc thay, cái tai nghe hiện tại của bạn lại dùng cổng 3.5mm. Chẳng nhẽ giờ phải bỏ thêm mấy trăm đô để nâng cấp tai nghe.

Thôi, tốn tiền lắm! Toàn bộ tiền tiết kiệm để mua điện thoại rùi. Giải pháp là bạn lên Shoppee sắm ngày một bộ Adapter để chuyển đổi từ cổng Lightning sang cổng 3.5mm, kiểu như này:

Adapter_Design_Pattern_1

Đây là ví dụ điển hình nhất về công dụng của Adapter.

Và còn rất nhiều ví dụ thực tế về công dụng của Adapter khác nữa.

Adapter_Design_Pattern_2

Trong lập trình cũng vậy, Adapter pattern được sử dụng khi bạn muốn thay thế một class cũ bằng một class mới. Adapter Pattern giúp các class có thể hoạt động cùng với nhau ngay cả khi chúng không thực sự tương thích với nhau.

Ưu điểm của Adapter Pattern là giúp chúng ta mở rộng hoặc cải thiện một thành phần nào đó trong hệ thống mà không làm ảnh hưởng tới hệ thống hiện tại, kể cả hệ thống hiện tại vẫn tiếp tục sử dụng các thành phần cũ đó.

Thực hành sử dụng Adapter Pattern

Để hiểu rõ hơn về Adapter Pattern, chúng ta sẽ cùng nhau thực hành một dự án xây dựng Calculator đơn giản.

Giả sử ứng dụng Calculator của chúng ta có một hàm chính phục vụ tính toán có 3 tham số đầu vào (number1, number2, operation). Tham số operation chính là các phép tính như: cộng, trừ, nhân, chia,.v.v…

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

export default Calculator;

Và trong hàm main, chúng ta sử dụng như sau:

/**
 * Main.js
 */
 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

Ok, hiện tại nó vẫn hoạt động tốt. Nhưng theo thời gian, chúng ta sẽ bổ sung thêm nhiều tính năng hơn nữa. Ví dụ như bổ sung thêm nhiều phép tính khác nữa. Giờ là lúc cần refactoring lại code cho nó đẹp hơn.

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

export default Calculator;

Tất nhiên, hàm main cũng phải sửa lại.

/**
 * Main.js
 */
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

Như bạn cũng đã thấy, sau khi chúng ta tiến hành refactoring lại code, thì đoạn code sử dụng ở hàm main đã không còn tương thích với phiên bản Calculator trước khi refactor. Để khắc phục điều này, mình sẽ tạo ra một Adapter.

/**
 * CalculatorAdapter.js
 */
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;

Ngon rồi đấy, giờ thì chúng ta có thể sử dụng được cả mã nguồn Calculator phiên bản trước khi refactor.

/**
 * Main.js
 */
 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

Như vậy là chúng ta đã ứng dụng thành công Adapter Pattern trong một dự án cụ thể rồi đấy. Nó cũng không quá phức tạp phải không!

Bạn đã ứng dụng Adaper bao giờ chưa? Mình rất vui nếu bạn chia sẻ lại kinh nghiệm trong phần bình luận.

💦 Đọc thêm về Javascript:

Dịch vụ phát triển ứng dụng mobile giá rẻ - chất lượng
Bài trước[Design Pattern] Hướng dẫn sử dụng Factory Method
Bài tiếp theoThực hành cài đặt và sử dụng Hàng đợi – Queue trong C++
Tên đầy đủ là Dương Anh Sơn. Tốt nghiệp ĐH Bách Khoa Hà Nội. Mình bắt đầu nghiệp coder khi mà ra trường chẳng xin được việc đúng chuyên ngành. Mình tin rằng chỉ có chia sẻ kiến thức mới là cách học tập nhanh nhất. Các bạn góp ý bài viết của mình bằng cách comment bên dưới nhé !

Bình luận. Cùng nhau thảo luận nhé!

avatar
  Theo dõi bình luận  
Thông báo