Facade Pattern là một trong những Pattern thuộc nhóm cấu trúc (Structural Pattern). Mẫu thiết kế này cung cấp một giao diện chung đơn giản thay cho một nhóm các giao diện có trong một hệ thống phức tạp. Hệ thống phức tạp này có thể là 1 thư viện (library), 1 framework, hay tập hợp các class phức tạp. Facade Pattern định nghĩa một giao diện ở một cấp độ cao hơn để giúp cho người dùng có thể dễ dàng sử dụng hệ thống này.
Mục đích của Facade Pattern là che giấu sự phức tạp của hệ thống con đằng sau. Thông qua Facade các hoạt động trở nên dễ dàng hơn.
Facade Pattern là mẫu thường thấy trong các thư viện phức tạp của PHP. Việc này giúp các lập trình viên dễ dàng tạo ra ứng dụng web mà không cần hiểu quá sâu về hệ thống.
Tìm hiểu thêm về Facade Pattern
Chú ý Facade Pattern không liên quan tới khái niệm Facade trong laravel
Trên đây là hình minh họa cho hệ thống khi không có Facade và khi có Facade
Tưởng tượng rằng, chúng ta đang phải làm việc với 1 thư viện hoặc 1 framework phức tạp với nhiều đối tượng khác nhau. Thông thường ta phải khởi tạo các đối tượng liên quan, theo dõi phụ thuộc, chạy hàm theo đúng thứ tự…
Điều này vô hình chung làm cho đoạn mã code của chúng ta sẽ gắn liền với việc triển khai của thư viện, framework. Việc này sẽ gây khó khăn cho việc bảo trì cũng như nâng cấp về sau này.
Facde Pattern chính là để giảm thiểu sự phức tạp hóa trong khâu tích hợp này.
A facade is a class that provides a simple interface to a complex subsystem which contains lots of moving parts. A facade might provide limited functionality in comparison to working with the subsystem directly. However, it includes only those features that clients really care about.
Một Facade là một class cung cấp giao diện đơn giản cho hệ thống con phức tạp cần tích hợp. Thông qua Facade tạo ra sự hạn chế tương tác với hệ thống con. Tuy nhiên việc này không quá quan trọng, vì Facade đã cung cấp các hành vi (hàm) mà khách hàng thực sự quan tâm.
Facade thực sự phát huy tác dụng khi chúng ta cần tích hợp một hệ thống phức tạp, tinh vi vào mã nguồn của mình, nhưng thực sự chúng ta chỉ cần dùng 1 phần nhỏ trong hệ thống phức tạp đó.
Giống như trong thực tế, khi bạn muốn mua 1 đôi giày trên trên sàn TMĐT như Tiki, Lazada, Shopee… Điều bạn cần làm là lựa chọn giày, đặt hàng, thanh toán và nhận hàng. Tất cả các hoạt động phức tạp phía sau đó bạn cũng không hề cần quan tâm. Các hoạt động như:
+ Hệ thống tiếp nhận đơn hàng điều hướng cho bộ phận tiếp nhận
+ Shipper đi lấy hàng tại nhà bán hàng chuyển về bưu cục quận gần dó
+ Xe tải chuyển về kho hàng chính của hệ thống
+ Lưu kho, phân loại hàng ( có rất nhiều hàng hóa, cần phân loại về các bưu cục tương ứng)
+ Cho xe vận chuyển về các bưu cục tương ứng. (Chuyển về bưu cục gần nơi bạn nhận hàng)
+ Shipper lấy hàng và đem giao tới địa chỉ bạn đặt.
….
Rất nhiều hoạt động phức tạp diễn ra. Nhưng chúng ta hoàn toàn không cần quan tâm đến điều đó. Điều này có thể hiểu như là 1 ví dụ về Facade Pattern.
Facade Pattern thông thường bao gồm
Facade: Facade nắm rõ được hệ thống con nào đảm nheiemj việc đáp ứng yêu cầu của client, nó sẽ chuyển yêu cầu của client đến các đối tượng hệ thống con tương ứng.
Subsystems: cài đặt các chức năng của hệ thống con, xử lý công việc được gọi bởi Facade. Các lớp này không cần biết Facade và không tham chiếu đến nó.
Client: đối tượng sử dụng Facade để tương tác với các subsystem.
Lợi điểm là
+ Ta có thể tách mã nguồn của mình ra khỏi sự phức tạp của hệ thống con
+ Hệ thống tích hợp thông qua Facade sẽ đơn giản hơn vì chỉ cần tương tác với Facade thay vì hàng loạt đối tượng khác.
+ Có thể đóng gói nhiều được thiết kế không tốt bằng 1 hàm có thiết kế tốt hơn
Nhược điểm này là class Facade của bạn có thể trở lên quá lớn, làm quá nhiều nhiệm vụ với nhiều hàm chức năng trong nó. Điều này sẽ dễ bị phá vỡ các quy tắc trong SOLID – nguyên lý lập trình hướng đối tượng
Ví dụ dựa trên hành động In tài liệu, đoạn mã sẽ mô phỏng như sau
<?php class Ink{ public function check(){ echo 'Đã check mực in'.PHP_EOL; } } class Paper { public function check(){ echo 'Đã check giấy'.PHP_EOL; } public function getPaperForPrinting(){ echo 'Chuẩn bị giấy để in'.PHP_EOL; } }; class PrinterEngine { public function loadDocument($file){ echo 'Tải tài liệu cần in'.PHP_EOL; } public function formatDocumentData(){ echo 'Format dữ liệu'.PHP_EOL; } public function warmUp(){ echo 'warm up Engine'.PHP_EOL; } public function prepareLaser(){ echo 'Chuẩn bị Laser'.PHP_EOL; } public function inkToPaper(){ echo 'In mực lên giấy'.PHP_EOL; } }; class PrinterFacade{ private static $instances; protected function __construct() { } protected function __clone() { } public function __wakeup() { throw new \Exception("Cannot unserialize singleton"); } public static function getInstance() { if (!isset(self::$instances)) { self::$instances = new self; } return self::$instances; } public function print($file){ $ink = new Ink; $paper = new Paper; $printerEngine = new PrinterEngine; $ink->check(); $paper->check(); $ink->check(); $printerEngine->loadDocument($file); $printerEngine->formatDocumentData(); $printerEngine->warmUp(); $printerEngine->prepareLaser(); $printerEngine->inkToPaper(); } } PrinterFacade::getInstance()->print('Tài liệu mật');
Kết quả
Đã check mực in Đã check giấy Đã check mực in Tải tài liệu cần in Format dữ liệu warm up Engine Chuẩn bị Laser In mực lên giấy
Chúng ta có thể thấy, Thay vì gọi hàng loạt hành động in phức tạp: chuẩn bị mực, giấy, làm ấm máy, in mực… Thì khi in chúng ta chỉ cần gọi Hàm Print là đủ.
Thông qua Facade chúng ta đã tối ưu hóa lại các bước cần làm. Mà cơ bản Các hoạt động khác chúng ta không quan tâm nhiều. Duy chỉ quan tâm điều duy nhất là đưa tài liệu vào và in ra bản cứng.
Thông thường Facade thường là Singleton do việc chúng ta chỉ cần 1 đối tượng Facade mà thôi.
Một lưu ý nhỏ cuối cùng là:
Façade Pattern tương tự với Adapter Pattern. Hai Pattern này làm việc theo cùng một cách, nhưng mục đích sử dụng của chúng khác nhau. Adapter Pattern chuyển đổi mã nguồn để làm việc được với mã nguồn khác. Nhưng Façade Pattern cho phép bao bọc mã nguồn gốc để nó có thể giao tiếp với mã nguồn khác dễ dàng hơn.
Hi vọng với bài viết trên đây các bạn hiểu phần nào về Facade Pattern trong PHP.
Nếu thấy bài viết hữu ích đừng tiếc 1 vài giây để like và share bài viết này tới nhiều Dev khác bạn nhé 😀
Bình luận: