The Facade Design Pattern

The Facade Design Pattern

facade
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:
facade2
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:
design-patterns-facade-uml
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.

Comments

  1. This is a very nice article. thank you for publishing this. i can understand this easily.!!..iOS Swift Online Training Hyderabad

    ReplyDelete

Post a Comment

Popular posts from this blog

iOS Architecture

Property vs Instance Variable (iVar) in Objective-c [Small Concept but Great Understanding..]

setNeedsLayout vs layoutIfNeeded Explained