Mẫu thiết kế Facade (Facade design pattern) là một trong những mẫu thiết kế thuộc nhóm cấu trúc (chẳng hạn như Adapter pattern và Decorator pattern). Nó được sử dụng để giúp các ứng dụng phía client dễ dàng tương tác với hệ thống.

Mẫu thiết kế Facade là gì?
Theo định nghĩa của GoF, mẫu thiết kế Facade:
Cung cấp một giao diện thống nhất cho một tập hợp các giao diện trong một hệ thống con. Facade Pattern định nghĩa một giao diện cấp cao hơn giúp cho hệ thống con dễ sử dụng hơn.
Giả sử chúng ta có một ứng dụng với tập hợp các giao diện để làm việc với cơ sở dữ liệu MySQL/Oracle và để tạo ra các loại báo cáo khác nhau như báo cáo HTML, báo cáo PDF, v.v. Khi đó, chúng ta sẽ có những tập giao diện khác nhau để làm việc với từng loại cơ sở dữ liệu. Ứng dụng phía client có thể sử dụng các giao diện này để lấy kết nối đến cơ sở dữ liệu cần thiết và tạo báo cáo.
Tuy nhiên, khi độ phức tạp tăng lên hoặc tên các hành vi trong giao diện gây nhầm lẫn, ứng dụng client sẽ gặp khó khăn trong việc quản lý. Vì vậy, chúng ta có thể áp dụng Facade design pattern để cung cấp một giao diện bao bọc (wrapper) bên trên các giao diện hiện có nhằm hỗ trợ ứng dụng client.
Mẫu thiết kế Facade – Tập hợp các giao diện
Chúng ta có thể có hai giao diện hỗ trợ, cụ thể là MySqlHelper và OracleHelper.
package com.journaldev.design.facade;
import java.sql.Connection;
public class MySqlHelper {
public static Connection getMySqlDBConnection(){
//get MySql DB connection using connection parameters
return null;
}
public void generateMySqlPDFReport(String tableName, Connection con){
//get data from table and generate pdf report
}
public void generateMySqlHTMLReport(String tableName, Connection con){
//get data from table and generate pdf report
}
}
package com.journaldev.design.facade;
import java.sql.Connection;
public class OracleHelper {
public static Connection getOracleDBConnection(){
//get Oracle DB connection using connection parameters
return null;
}
public void generateOraclePDFReport(String tableName, Connection con){
//get data from table and generate pdf report
}
public void generateOracleHTMLReport(String tableName, Connection con){
//get data from table and generate pdf report
}
}
Giao diện của mẫu thiết kế Facade
Chúng ta có thể tạo một giao diện cho Facade pattern như bên dưới. Lưu ý việc sử dụng Enum trong Java để đảm bảo tính an toàn kiểu dữ liệu (type safety).
package com.journaldev.design.facade;
import java.sql.Connection;
public class HelperFacade {
public static void generateReport(DBTypes dbType, ReportTypes reportType, String tableName){
Connection con = null;
switch (dbType){
case MYSQL:
con = MySqlHelper.getMySqlDBConnection();
MySqlHelper mySqlHelper = new MySqlHelper();
switch(reportType){
case HTML:
mySqlHelper.generateMySqlHTMLReport(tableName, con);
break;
case PDF:
mySqlHelper.generateMySqlPDFReport(tableName, con);
break;
}
break;
case ORACLE:
con = OracleHelper.getOracleDBConnection();
OracleHelper oracleHelper = new OracleHelper();
switch(reportType){
case HTML:
oracleHelper.generateOracleHTMLReport(tableName, con);
break;
case PDF:
oracleHelper.generateOraclePDFReport(tableName, con);
break;
}
break;
}
}
public static enum DBTypes{
MYSQL,ORACLE;
}
public static enum ReportTypes{
HTML,PDF;
}
}
Chương trình phía client sử dụng Mẫu thiết kế Facade
Bây giờ, hãy cùng xem mã phía client trong hai trường hợp: không sử dụng Facade pattern và sử dụng giao diện của Facade pattern.
package com.journaldev.design.test;
import java.sql.Connection;
import com.journaldev.design.facade.HelperFacade;
import com.journaldev.design.facade.MySqlHelper;
import com.journaldev.design.facade.OracleHelper;
public class FacadePatternTest {
public static void main(String[] args) {
String tableName="Employee";
//generating MySql HTML report and Oracle PDF report without using Facade
Connection con = MySqlHelper.getMySqlDBConnection();
MySqlHelper mySqlHelper = new MySqlHelper();
mySqlHelper.generateMySqlHTMLReport(tableName, con);
Connection con1 = OracleHelper.getOracleDBConnection();
OracleHelper oracleHelper = new OracleHelper();
oracleHelper.generateOraclePDFReport(tableName, con1);
//generating MySql HTML report and Oracle PDF report using Facade
HelperFacade.generateReport(HelperFacade.DBTypes.MYSQL, HelperFacade.ReportTypes.HTML, tableName);
HelperFacade.generateReport(HelperFacade.DBTypes.ORACLE, HelperFacade.ReportTypes.PDF, tableName);
}
}
Như bạn có thể thấy, việc sử dụng giao diện Facade pattern là cách đơn giản và rõ ràng hơn rất nhiều để tránh phải xử lý quá nhiều logic ở phía client. Lớp JDBC DriverManager dùng để lấy kết nối cơ sở dữ liệu là một ví dụ điển hình cho mẫu thiết kế Facade.
Những điểm quan trọng về Mẫu thiết kế Facade
- Mẫu thiết kế Facde giống như một thành phần hỗ trợ cho các ứng dụng phía client, nó không ẩn các giao diện của hệ thống con khỏi client. Việc có sử dụng Facade hay không hoàn toàn phụ thuộc vào mã phía client.
- Mẫu thiết kế Facade có thể được áp dụng tại bất kỳ thời điểm nào trong quá trình phát triển, thường là khi số lượng giao diện tăng lên và hệ thống trở nên phức tạp.
- Các giao diện của hệ thống con không biết đến sự tồn tại của Facade và không nên có bất kỳ tham chiếu nào đến giao diện Facade.
- Mẫu thiết kế Facade nên được áp dụng cho các giao diện có chức năng tương tự nhau; mục đích là để cung cấp một giao diện duy nhất thay vì nhiều giao diện thực hiện các công việc tương tự.
- Chúng ta có thể kết hợp Factory pattern với Facade để cung cấp giao diện tốt hơn cho hệ thống phía client.
->> Tìm hiểu thêm: Những design pattern thông dụng trong Java và ví dụ