The Facade Design Pattern is implemented by defining a single interface that interacts with several interfaces within a system. It enforces the principle of Least Knowledge or Law of Demeter by reducing the amount of classes an object depends on. Extra logic can optionally be added to the Facade as needed.
Example Problem:
Consider a scenario where you need to generate reports for a sales system. Your sales system includes two interfaces (a point of sale machine and a debit machine). Client code will need to interact with each of these interfaces to generate a report. As the system grows the class handling these details will also grow.
Examples of the point of sales and debit machine interfaces:
1 2 3 4 5 6 7 8 9 10 | public interface POSMachine { void login(); void endSalesForDay(); POSReport generateReport(); } public interface DebitMachine { void completeDaySales(); DebitReport generateReport(); } |
Example of the client implementation
1 2 3 4 5 6 7 8 9 10 | public class ReportTest { public ReportTest() { posMachine.login(); posMachine.endSalesForDay(); POSReport posReport = posMachine.generateReport(); debitMachine.completeDaySales(); DebitReport debitReport = debitMachine.generateReport(); } } |
Implementing the Facade Pattern
While the above example is simple it could become more complicated as the system potentially grows. For simplicity I assume the different sales machines implement
a Machine
and the reports implement
a Report
. Let’s implement the Facade
pattern to simplify the client code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public interface ReportFacade { Report generateReport(Machine machine); } public class ReportFacadeImpl implements ReportFacade { public Report generateReport(Machine machine) { if (machine instanceOf POSMachine) { POSMachine posMachine = (POSMachine) machine; posMachine.login(); posMachine.endSalesForDay(); return posMachine.generateReport(); } else if (machine instanceOf DebitMachine) { DebitMachine debitMachine = (DebitMachine) machine; debitMachine.completeDaySales(); return debitMachine.generateReport(); } } } |
The now simplified client code
Utilizing the ReportFacade greatly simplifies the code:
1 2 3 4 5 6 | public class ReportTest { public ReportTest() { POSReport posReport = reportFacade.generateReport(posMachine); DebitReport debitReport = reportFacade.generateReport(debitMachine); } } |
Summary
The client code is now simplified. New functionality can easily be added to the Facade as needed. The client code now adheres to the principle of least knowledge.