Adapter thuộc nhóm structural (nhóm cấu trúc). Nó cho phép các đối tượng không có chung giao diện có thể làm việc với nhau.

Vấn đề
Hãy tưởng tượng rằng bạn đang tạo một ứng dụng theo dõi thị trường chứng khoán. Ứng dụng tải xuống dữ liệu từ nhiều nguồn ở định dạng XML và sau đó hiển thị các biểu đồ và sơ đồ đẹp mắt cho người dùng.
Ta có thể chọn cải thiện ứng dụng bằng cách tích hợp analysis library của bên thứ 3. Nhưng nên lưu ý: analysis library chỉ hoạt động với dữ liệu ở định dạng JSON.

Ta có thể thay đổi library để làm việc với XML. Tuy nhiên, điều này có thể phá vỡ một số code hiện tại dùng thư viện ấy. Và tệ hơn, trong trường hợp không có quyền truy cập vào source code của thư viện ngay từ đầu, khiến cho cách này không thực dụng.
Giải pháp
Ta có thể tạo một adapter. Đây là một object đặc biệt chuyển đổi interface của một object để object kia có thể hiểu được.
Adapter bao bọc một trong object để che đi quá trình chuyển đổi. Object được bọc thậm chí không nhận biết được adapter.
Ví dụ: có thể bọc một đối tượng hoạt động theo đơn vị mét và ki lô mét bằng adapter có thể chuyển đổi tất cả dữ liệu sang các đơn vị đo lường Anh như feet và dặm.
Adapters không chỉ có thể chuyển đổi dữ liệu thành nhiều định dạng khác nhau mà còn có thể giúp các đối tượng có giao diện khác nhau cộng tác. Nó hoạt động như sau:
-
Adapter có giao diện, tương thích với một trong các đối tượng hiện có. Sử dụng giao diện này, đối tượng hiện có có thể gọi các phương thức của adapter một cách an toàn.
-
Khi được gọi, adapter sẽ chuyển yêu cầu đến đối tượng thứ hai, nhưng theo một định dạng và thứ tự mà đối tượng thứ hai mong đợi.
Đôi khi, thậm chí có thể tạo adapter hai chiều có thể chuyển đổi theo cả hai hướng.

Hãy quay lại ứng dụng thị trường chứng khoán đã tạo lúc nãy. Để giải quyết vấn đề khó xử của các định dạng không tương thích, ta có thể tạo adapter XML sang JSON cho mọi class của analysis library mà code đang làm việc trực tiếp với. Sau đó, bạn điều chỉnh code để chỉ giao tiếp với thư viện thông qua các adapter này.
Khi một adapter nhận được một cuộc gọi, nó sẽ dịch dữ liệu XML đến thành một cấu trúc JSON và chuyển cuộc gọi đến các phương thức thích hợp của một đối tượng phân tích được bao bọc.
Cấu trúc
Object adapter!

Trong đó: - Client là một class chứa logic nghiệp vụ hiện có của chương trình.
-
Client Interface mô tả một giao thức mà các lớp khác phải tuân theo để có thể cộng tác với client.
-
Service là một số lớp hữu ích (thường là bên thứ 3 hoặc kế thừa). Client không thể sử dụng trực tiếp class này vì nó có interface không tương thích.
-
Adapter là một lớp có thể hoạt động với cả client và service: nó triển khai ClientInterface trong khi gói đối tượng service. Adapter nhận các cuộc gọi từ client thông qua giao diện adapter và chuyển chúng thành các cuộc gọi tới đối tượng service được bao bọc theo định dạng mà nó có thể hiểu được.
Client không cần ghép nối với một adapter cụ thể miễn là nó hoạt động với adapter thông qua ClientInterface. Nhờ đó, ta có thể giới thiệu các loại adapter mới vào chương trình mà không phá vỡ mã client hiện có.
Khá hữu ích trong trường hợp interface của service cần thay đổi hoặc thay thế, vì có thể tạo một adapter mới mà không cần thay đổi client.
Class adapter

Class Adapter không cần bao bọc bất cứ đối tượng nào bởi vì nó kế thừa từ cả client và service. Adapter hoạt động bằng cách ghi đè những method của lớp cha. Kết quả là adapter có thể được sử dụng thay cho một class client.
Ưu điểm
- Single Responsibility Principle: có thể tách biệt mã xây dựng phức tạp khỏi logic hoạt động của chương trình.
- Open/Closed Principle: có thể giới thiệu các loại adapter mới vào chương trình mà không vi phạm mã hiện có, miễn là chúng hoạt động với adapter thông qua ClientInterface.
Nhược điểm
Độ phức tạp tổng thể tăng lên vì cần giới thiệu một tập hợp các interface và class mới. Đôi khi, việc thay đổi lớp service sao cho phù hợp với code cũ sẽ đơn giản hơn.
Refer
Nguồn: https://refactoring.guru/design-patterns/adapter
Ví dụ bằng PHP: https://refactoring.guru/design-patterns/adapter/php/example