Design pattern trong Java: Adapter

Khái niệm

Adapter là một design pattern thuộc loại Structure(Cấu trúc) cho phép các đối tượng trong interface không tương thích cộng tác.

Bài toán?

Hãy tưởng tượng bạn đang tạo ra 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 kho từ nhiều nguồn ở định dạng XML và sau đó hiển thị các biểu đồ và sơ đồ cho người dùng.

Đến một thời điểm, bạn quyết định cải thiện ứng dụng bằng cách tích hợp thư viện phân tích thông minh của bên thứ 3. Nhưng có một điểm lưu ý: thư viện phân tích đó chỉ hoạt động với dữ liệu dạng JSON.

Bạn không thể giữ nguyên cấu trúc XML vì thư viện phân tích không tương thích với ứng dụng

Bạn có thể thay đổi thư viện để làm việc với XML. Tuy nhiên nó có thể gây ra lỗi với những đoạn code trong thư viện. Hay bạn cũng có thể là không có quyền truy cập vào source của thư viện khiến cho việc thực hiện phương pháp này không hiệu quả.

Giải pháp

Bạn có thể tạo một bộ chuyển đổi (Adapter). Đây là một đối tượng đặc biệt để chuyển đổi interface của một đối tượng để đối tượng khác có thể hiểu được nó.

Một adapter bao bọc trong các đối tượng để che giấu sự phức tạp của quá trình chuyển đổi diễn ra bên trong nó. Ví dụ: bạn có thể bọc một đối tượng hoạt động theo đơn vị mét và ki lô mét bằng bộ chuyển đổi có thể chuyển đổi tất cả dữ liệu sang các đơn vị đo lường khác như feet và dặm.

Một adapter 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ó interface khác nhau cộng tác. Đây là cách nó hoạt động: 

  1. Bộ adapter có interface, tương thích với một trong các object hiện có.
  2. Sử dụng interface này, object hiện có có thể gọi các phương thức của adapter một cách an toàn.
  3. Khi phương thức đượ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, adapter có thể chuyển đổi theo cả hai hướng.

Hãy quay lại bài toán chứng khoán ở trên. Để giải quyết vấn đề về các định dạng không tương thích, bạn có thể tạo một Adapter từ XML sang JSON cho mọi class của thư viện phân tích mà code của bạn gọi đến chúng. Sau đó điều chỉnh để khi giao tiếp với thư viện này sẽ thông qua adapter.

Kiến trúc

Object adapter

Việc triển khai này sử dụng nguyên tắc cấu thành đối tượng. Adapter implements interface và bao bọc đối tượng kia. Nó được thực hiện trong tất cả ngôn ngữ lập trình phổ biến.

  1. Client là một class chứa logic nghiệp vụ hiện có của app.
  2. Client Interface mô tả một giao thức mà các class khác phải tuân theo để cộng tác với Client.
  3. Service là một số class (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.
  4. Adapter là một class có thể hoạt động với cả client và service. Nó triển khai Client interface trong khi bao bọc các service. Adapter nhận các request từ Client interface và chuyển chúng thành request đến các dịch vụ được chuyển đổi thành định dạng mà Service có thể hiểu được.
  5. Client code không được gọi trực tiếp đến Adapter mà thông qua Client interface. Điều này có thể hữu ích khi Service được thay đổi hoặc thay thế. Bạn chỉ cần tạo một Adapter mới mà không cần thay đổi code phía Client.

Class adapter

Việc triển khai này sử dụng tính kế thừa: Adapter kế thừa các interface của 2 đối tượng cùng một lúc. Tuy nhiên thì cách này chỉ có thể được thực hiện trong các ngôn ngữ lập trình có hỗ trợ đa kế thừa như C++.

  1. Class Adapter không cần phải wrap object nào cả vì nó kế thừa từ Client và Service. Việc điều chỉnh xảy ra trong các phương thức bị ghi đè. Adapter có thể được sử dụng bở các class Client hiện có.

Khi nào thì áp dụng?

  • Sử dụng Adapter khi bạn muốn sử dụng một số class hiện có, nhưng interface của nó không tương thích với code của bạn.
  • Sử dụng pattern khi bạn muốn sử dụng lại một số class con hiện có thiếu một số chức năng phổ biến không thể thêm vào class cha.

Cách triển khai

  1. Đảm bảo rằng bạn có ít nhất 2 class có interface không tương thích:
    • Một class Service mà bạn không thể thay đổi (thường là bên thứ 3, kế thừa hoặc với nhiều phụ thuộc hiện có). Một hoặc một số class Client mà có thể sử dụng Service.
    • Khai báo interface Client và mô tả các chức năng mà Client gọi đến Service.
  2. Tạo class Adapter và làm cho nó tuân theo interface Client. Để trống tất cả các phương thức.
  3. Thêm một field vào class Adapter để tham chiếu đến Service. Thông thường sẽ khởi tạo field này qua constructor, đôi khi nó sẽ thuận tiện hơn khi gọi các phương thức của nó.
  4. Triển khai tất cả các phương thức của interface Client trong Adapter. Adapter sẽ xử lý interface hoặc chuyển đổi định dạng dữ liệu và sẽ uỷ thác công việc cho phía Service.
  5. Client sẽ sử dụng Adapter thông qua Client interface. Điều này sẽ cho phép bạn thay đổi hoặc mở rộng Adapter mà không ảnh hưởng đến code của Client.

Ưu và nhược điểm

  • Nguyên tắc Single Responsibility. Bạn có thể tách interface hoặc dữ liệu chuyển đổi khỏi logic nghiệp vụ chính của chương trình.
  • Nguyên tắc Open/Close. Bạn có thể thêm bớt Adapter mới mà không làm thay đổi code của Client
  • Độ phức tạp của code sẽ bị tăng lên vì bạn cần các interface và class mới. Đôi khi việc thay đổi class Service phù hợp với code của bạn sẽ có thể đơn giản hơn.

Demo

Các bạn tham khảo demo Design Pattern Adapter tại đây nhé

Như vậy là mình vừa mới giới thiệu thêm một Design Pattern nữa. Nếu có gì không hiểu thì các bạn comment phía dưới. Chúc các bạn có ngày học tập hiệu quả, và đừng quên tham gia Group để trao đổi kiến thức nhiều hơn nhé.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x