Adapter Pattern là một trong những Structural design patterns đây là các mẫu Design Pattern được thiết kế để xây dựng sự liên kết, quan hệ giữa các thực thể với nhau.
Trong bài viết này chúng ta sẽ tìm hiểu về Adapter Pattern và cách sử dụng trong ngôn ngữ lập trình PHP.
Adapter Pattern là gì?
Adapter Pattern cho phép các lớp (class, interface) không tương thích với nhau có thể hoạt động được với nhau. Đối tượng hỗ trợ việc việc được gọi là Adapter.
Hoặc theo wiki thì
Adapter Pattern cho phép các lớp không tương thích hoạt động cùng nhau bằng cách chuyển đổi giao diện (interface) của một lớp thành giao diện mà khách hàng mong đợi.
Chúng ta cũng thường biết tới Adapter Pattern với tên gọi khác là Wrapper Pattern.
Xem thêm Adapter Pattern trên wiki
Ví dụ Adapter trong thực tế
Màn hình máy tính, Laptop, Điện thoại… các thiết bị này đều cần adapter chuyển đổi từ dòng diện xoay chiều 220V về dòng điện 1 chiều 12 V để thiết bị hoạt động.
Chúng ta hiểu ở đây rằng, Nguồn điện được cung cấp ( có sẵn điện lưới), thiết bị điện đương nhiên cần điện mới có thể hoạt động. Tuy nhiên, dòng điện xoay chiều 220V lại không hề tương thích với các thiết bị đó. Đây là lúc xuất hiện của Adapter, bằng một cách nào đấy, Adapter chuyển đổi dòng điện xoay chiều về dòng điện tương thích từng thiết bị điện.
Adapter Pattern giải quyết các vấn đề gì?
+ Giúp các lớp có giao diện không tương thích với nhau có thể tương tác/làm việc được với nhau
+ Tái sử dụng lại một lớp, mặc dù lớp đó chưa có giao diện tương thích với yêu cầu . Như trong ví dụ thực tế là có sẵn nguồn điện xoay chiều rồi, nhưng làm sao để có thể sử dụng nó cho các thiết bị điện 1 chiều.
Đó là 2 lý do cơ bản để chúng ta xác định khi nào nên sử dụng Adapter Pattern. Ứng dụng việc này sẽ tương ứng với các ý sau đây.
+ Sử dụng Adapter Pattern khi bạn muốn sử dụng class đã có sẵn, nhưng giao diện của nó không tương thích với phần còn lại của project (bộ mã bạn đang muốn đưa vào sử dụng)
+ Sử dụng khi bạn muốn sử dụng lại các lớp dẫn xuất (kế thừa) nhưng có 1 vài function (hàm ) bị thiếu, các hàm này lại không thể thêm vào lớp cha được.
Để xử lý trong trường hợp này bạn có thể kế thừa và thêm các hàm vào các class mới tạo tạo ra đó. Tuy vậy nó sẽ thực sự tệ khi mà nếu bạn có nhiều lớp dẫn xuất và phải copy sang từng class một. Điều này càng tệ hại hơn khi cần sửa đổi và nâng cấp. Đó là khi bạn nên dùng Adapter Pattern
Cài đặt Adapter Pattern trong PHP như thế nào?
Một Adapter Pattern thường bao gồm các thành phần cơ bản như sau
Target: Là class/interface chứa các chức năng mà được sử dụng bởi Client.
Adaptee: Đối tượng mà có 1 số chức năng hữu ích (đang cần được sử dụng). Nhưng giao diện hiện tại của Adaptee không tương thích với Client.
Adapter: lớp chuyển đổi, thông qua Adapter sẽ làm cho Adaptee tương tích với Target. Qua đó kết nối được Adaptee với Client
Client: Lớp sử dụng các đối tượng đối tượng có interface Target.
Có 2 cách để thực hiện cài đặt Adapter Pattern mà chúng ta sẽ xem xét ngay dưới đây.
Cài đặt theo Object Adapter – Composition (Chứa trong hoặc thành phần)
Với mô hình này, một lớp mới Adapter sẽ tham chiếu đến 1 hoặc nhiều đối tượng Adaptee ( đối tượng đang không có sự tương thích), đồng thời Adapter này sẽ implement interface (Target) mà Client mong muốn.
Khi cài đặt các phương thức của Interface Target, trong các phương thức này sẽ gọi các phương thức (hàm) cần thiết thông qua đối tượng Adapter.
Ví dụ với hình minh họa trên
Server là Adaptee: chứa hàm serviceMethod
Client Interface chính là Target: Interface có các hàm mà Client mong muốn được thực hiện. Trong Target có hàm method
Adapter sẽ implement Target, trong hàm method sẽ gọi tới serviceMethod tương ứng của đối tượng Adaptee.
Cài đặt theo Class Adapter – Inheritance (Kế thừa)
Trong mô hình này, Adapter sẽ kế thừa lớp không tương thích Adaptee, đồng thời implement interface Target (Interface mà có hàm Client đang mong muốn sử dụng).
Trong Adapter, các phương thức cài đặt của Target sẽ gọi các hàm từ bên Adaptee.
Trong hình minh họa bên trên cụ thể là
Adapter kế thừa Service và implement Existing Class, trong hàm method (cài đặt từ Existing Class) sẽ gọi hàm serviceMethod (hàm từ class Service – Adaptee)
Ví dụ với Adapter Pattern trong PHP
Yêu cầu: Một người Việt muốn trao đổi với một người Nhật. Cả 2 người này không biết ngôn ngữ của nhau nên cần phải có một người thông dịch từ Tiếng Việt sang Tiếng Nhật.
Trường hợp này được mô hình hóa với Adapter Pattern như sau:
Client: Là người Việt, vì Người Việt đang muốn gửi thông điệp tới người Nhật
Adaptee: Được hiểu là cách người Nhật hiểu được thông điệp truyền tới (Ở ví dụ này người Nhật chỉ hiểu tiếng Nhật). Nên việc truyền thông điệp tiếng Việt tới sẽ không được. Chính vì vậy chúng ta cần có Adapter
Adapter: Đây là thông dịch viên, có nhiệm vụ dịch tiếng Việt sang tiếng Nhật và gửi đi.
Target: Đây là nội dung thông điệp mà người Việt muốn gửi đi.
Ví dụ với mô hình Composition – Adaptee là thành phần trong Adapter
<?php namespace CodeTuTam\AdapterPattern; interface Target{ public function send($message); } class Adaptee{ public function receive($message):void{ echo 'Nhận thông tin Adapter....'.PHP_EOL; echo $message.PHP_EOL; } } // Người thông dịch class Adapter implements Target{ protected $adaptee; public function __construct(Adaptee $adaptee){ $this->adaptee=$adaptee; } //Chuyển từ tiếng việt sang tiếng nhật private function translate($message){ // Trả về tiếng nhật tương ứng return "こんにちは"; } public function send($message){ $JPMessage = $this->translate($message); $this->adaptee->receive($JPMessage); } } class Client{ public function send(){ $target = new Adapter(new Adaptee); $target->send('Xin chào'); } } $client = new Client; $client->send();
Kết quả là
Nhận thông tin Adapter.... こんにちは
Ví dụ theo mô hình kế thừa – Inheritance
<?php namespace CodeTuTam\AdapterPattern; interface Target{ public function send($message); } class Adaptee{ public function receive($message):void{ echo 'Nhận thông tin Adapter....'.PHP_EOL; echo $message.PHP_EOL; } } // Người thông dịch class Adapter extends Adaptee implements Target{ //Chuyển từ tiếng việt sang tiếng nhật private function translate($message){ // Trả về tiếng nhật tương ứng return "こんにちは"; } public function send($message){ $JPMessage = $this->translate($message); $this->receive($JPMessage); } } class Client{ public function send(){ $target = new Adapter(new Adaptee); $target->send('Xin chào'); } } $client = new Client; $client->send();
Kết luận
Adapter Pattern được ứng dụng rộng rãi không chỉ trong PHP mà còn nhiều ngôn ngữ khác. Adapter Pattern giúp tương thích được với mọi tình huống cần nâng cấp hệ thống cũ. Nó làm cho hệ thống hiệu quả hơn thông qua việc làm cho các component cũ giao tiếp với nhau dễ dàng hơn dù không liên quan đến nhau.
Bạn có thể xem thêm về Design Pattern thông qua chuỗi bài dịch trên cộng đồng C việt được tổng hợp tại đây.
Ngoài ra dù làm theo Adapter Pattern bạn cần chú ý vẫn phải tuân thủ theo nguyên lý SOLID để có được một ứng dụng tốt.
Hi vọng với các ví dụ trên đây phần nào giúp các bạn hiểu thêm về Adapter Pattern và cách ứng dụng vào trong ứng dụng, hệ thống hiện tại.
Nếu bạn thấy bài viết này hữu ích, hãy like và chia sẻ giúp CodeTuTam bạn nhé.