Structural Design Patterns: Facade Pattern
As developers most of the time we have to deal with complex systems, with many dependencies and even non existing documentation at all.
In these situations finding a way to tackle those challenges is essential. The most common way to deal with it, is to hide all those dependencies and specify a front facing interface.
The pattern to use in order to achieve is the facade pattern.
Somehow you end it up with a very complex system which generates reports in various ways. The system generates reports as xml files, csv files and even generates reports from a database.
The report generated in xml files extracts statistics based on a location, the report generated in csv files has to do with timeseries data and the database report about usage data.
The functionalities described above need to be incorporated to a web application.
The first step would be to create some interfaces based on each report.
The first interface will be the Geolocation report. By giving a location and a distance, a report shall be generated with locations within the distance specified from the point.
package com.gkatzioura.design.structural.facade; public interface GeolocationReport { String[][] generate(Double lat,Double lng,Double distance); }
The Geolation report will be based on the xml reports generated from our system. Thus the implementation would be based on the xml report.
package com.gkatzioura.design.structural.facade; public class XMLGeolocationReport implements GeolocationReport { @Override public String[][] generate(Double lat, Double lng, Double distance) { /** * http requests to retrieve the xml * iterate the xml using stax */ return new String[][]{}; } }
Our next report will have to do with time series data. Two dates will be given as an argument and thus the data needed will be retrieved.
package com.gkatzioura.design.structural.facade; import java.util.Date; public interface TimeSeriesReport { String[][] generate(Date start,Date end); }
Since the csv report is the one generated with time series data, our implementation will be based on the csv report of our system.
package com.gkatzioura.design.structural.facade; import java.util.Date; public class CSVTimeSeriesReport implements TimeSeriesReport { @Override public String[][] generate(Date start, Date end) { /** * retrieve the csv and iterate line by line within the time limits */ return new String[][]{}; } }
The last step is the user usage report. A uuid representing the user shall be given.
package com.gkatzioura.design.structural.facade; import java.util.UUID; public interface UsageReport { String[][] report(UUID uuid); }
The usage report will be based on the database report.
package com.gkatzioura.design.structural.facade; import java.util.UUID; public class SQLUsageReport implements UsageReport { @Override public String[][] report(UUID uuid) { return new String[0][]; } }
So far we have abstracted the main functionalities of our system. Our next step is to create the facade which uses all those functionalities and bridges the gap between our web application needs and the the system that provides the information.
For example based on the user’s usage we need to have data based on the time and location of the user.
package com.gkatzioura.design.structural.facade; import java.util.Date; import java.util.UUID; public interface UserUsageFacade { String[][] usageOn(UUID user, Date from, Double lat,Double lng); }
And the implementation will use the report implementations in order to create the report that suits our web application.
package com.gkatzioura.design.structural.facade; import java.util.Date; import java.util.UUID; public class UserUsageFacadeImpl implements UserUsageFacade { private final GeolocationReport geolocationReport; private final TimeSeriesReport timeSeriesReport; private final UsageReport usageReport; private final double DEFAULT_DISTANCE = 20d; private final int DEFAULT_TIME_RANGE = 20; public UserUsageFacadeImpl(GeolocationReport geolocationReport, TimeSeriesReport timeSeriesReport, UsageReport usageReport) { this.geolocationReport = geolocationReport; this.timeSeriesReport = timeSeriesReport; this.usageReport = usageReport; } @Override public String[][] usageOn(UUID user, Date from, Double lat, Double lng) { String[][] locationData = geolocationReport.generate(lat,lng,DEFAULT_DISTANCE); Date to = Date.from(from.toInstant().plusSeconds(DEFAULT_TIME_RANGE)); String[][] timeSetiesData = timeSeriesReport.generate(from,to); String[][] usageData = usageReport.report(user); /** * Generate the report based on the data retrieved */ return new String[][] {}; } }
You can find the source code on github.
Also you can find some helpful articles on the Adapter Pattern, the Decorator Pattern, the Composite Pattern and the Bridge Pattern.
Published on Java Code Geeks with permission by Emmanouil Gkatziouras, partner at our JCG program. See the original article here: Structural Design Patterns: Facade Pattern Opinions expressed by Java Code Geeks contributors are their own. |
String[][]? Really? Java is an object oriented language and you represent value classes like Location information as String[][]? You lost me right there, I stopped reading. The quality of the information this site publishes has gone into the toilet. This is terrible advice and examples for someone new to Java. I recommend anyone reading this comment to ignore this article, it is teaching things that were wrong in 1997 designs.
I agree on passing back an object containing the information and various actions, is the right way. However by doing so the article would become way more big and out of the original scope. What in reality string[][] stands for is the information given back. It could be any object that fits the use case. The article is not about recommending using string arrays or representing locations in string. If it was, it would state so.
Since is misleading it will change (on the original article).