The Facade Design Pattern
The Facade Design Pattern
The Facade design pattern provides a single interface to a complex subsystem. Instead of exposing the user to a set of classes and their APIs, you only expose one simple unified API.
The following image explains this concept:
The user of the API is completely unaware of the complexity that lies beneath. This pattern is ideal when working with a large number of classes, particularly when they are complicated to use or difficult to understand.
The Facade pattern decouples the code that uses the system from the interface and implementation of the classes you’re hiding; it also reduces dependencies of outside code on the inner workings of your subsystem. This is also useful if the classes under the facade are likely to change, as the facade class can retain the same API while things change behind the scenes.
For example, if the day comes when you want to replace your backend service, you won’t have to change the code that uses your API as it wont’ change.
How to Use the Facade Pattern
Currently you have
PersistencyManager
to save the album data locally and HTTPClient
to handle the remote communication. The other classes in your project should not be aware of this logic, as they will be hiding behind the facade of LibraryAPI
.
To implement this pattern, only
LibraryAPI
should hold instances of PersistencyManager
and HTTPClient
. Then, LibraryAPI
will expose a simple API to access those services.
The design looks like the following:
LibraryAPI
will be exposed to other code, but will hide the HTTPClient
and PersistencyManager
complexity from the rest of the app.
Open LibraryAPI.swift and add the following constant properties to the class:
private let persistencyManager: PersistencyManager private let httpClient: HTTPClient private let isOnline: Bool |
isOnline
determines if the server should be updated with any changes made to the albums list, such as added or deleted albums.
You now need to initialize these variables via
init
. Add the initializer to the class next:override init() { persistencyManager = PersistencyManager() httpClient = HTTPClient() isOnline = false super.init() } |
The HTTP client doesn’t actually work with a real server and is only here to demonstrate the usage of the facade pattern, so
isOnline
will always be false
.
Next, add the following three methods to LibraryAPI.swift:
func getAlbums() -> [Album] { return persistencyManager.getAlbums() } func addAlbum(album: Album, index: Int) { persistencyManager.addAlbum(album, index: index) if isOnline { httpClient.postRequest("/api/addAlbum", body: album.description) } } func deleteAlbum(index: Int) { persistencyManager.deleteAlbumAtIndex(index) if isOnline { httpClient.postRequest("/api/deleteAlbum", body: "\(index)") } } |
Take a look at
addAlbum(_:index:)
. The class first updates the data locally, and then if there’s an internet connection, it updates the remote server. This is the real strength of the Facade; when some class outside of your system adds a new album, it doesn’t know — and doesn’t need to know — of the complexity that lies underneath.
Note: When designing a Facade for classes in your subsystem, remember that nothing prevents the client from accessing these “hidden” classes directly. Don’t be stingy with defensive code and don’t assume that all the clients will necessarily use your classes the same way the Facade uses them.
This is a very nice article. thank you for publishing this. i can understand this easily.!!..iOS Swift Online Training Hyderabad
ReplyDelete