[](http://cdn1.raywenderlich.com/wp-content/uploads/2013/07/facade.jpg)
外觀模式在復雜的業務系統上提供了簡單的接口。如果直接把業務的所有接口直接暴露給使用者,使用者需要單獨面對這一大堆復雜的接口,學習成本很高,而且存在誤用的隱患。如果使用外觀模式,我們只要暴露必要的 API 就可以了。
下圖演示了外觀模式的基本概念:
[](http://cdn1.raywenderlich.com/wp-content/uploads/2013/07/facade2-480x241.png)
API 的使用者完全不知道這內部的業務邏輯有多么復雜。當我們有大量的類并且它們使用起來很復雜而且也很難理解的時候,外觀模式是一個十分理想的選擇。
外觀模式把使用和背后的實現邏輯成功解耦,同時也降低了外部代碼對內部工作的依賴程度。如果底層的類發生了改變,外觀的接口并不需要做修改。
舉個例子,如果有一天你想換掉所有的后臺服務,你只需要修改 API 內部的代碼,外部調用 API 的代碼并不會有改動。
### 如何使用外觀模式
現在我們用?`PersistencyManager`?來管理專輯數據,用?`HTTPClient`?來處理網絡請求,項目中的其他類不應該知道這個邏輯。他們只需要知道?`LibraryAPI`?這個“外觀”就可以了。
為了實現外觀模式,應該只讓?`LibraryAPI`?持有?`PersistencyManager`?和?`HTTPClient`?的實例,然后?`LibraryAPI`?暴露一個簡單的接口給其他類來訪問,這樣外部的訪問類不需要知道內部的業務具體是怎樣的,也不用知道你是通過?`PersistencyManager`?還是?`HTTPClient`?獲取到數據的。
大致的設計是這樣的:
[](http://cdn2.raywenderlich.com/wp-content/uploads/2013/08/design-patterns-facade-uml-480x71.png)
`LibraryAPI`?會暴露給其他代碼訪問,但是?`PersistencyManager`?和?`HTTPClient`?則是不對外開放的。
打開?`LibraryAPI.swift`?然后添加如下代碼:
~~~
private let persistencyManager: PersistencyManager
private let httpClient: HTTPClient
private let isOnline: Bool
~~~
除了兩個實例變量之外,還有個?`Bool`?值:?`isOnline`?,這個是用來標識當前是否為聯網狀態的,如果是聯網狀態就會去網絡獲取數據。
我們需要在?`init`?里面初始化這些變量:
~~~
override init() {
persistencyManager = PersistencyManager()
httpClient = HTTPClient()
isOnline = false
super.init()
}
~~~
`HTTPClient`?并不會直接和真實的服務器交互,只是用來演示外觀模式的使用。所以?`inOnline`這個值我們一直設置為?`false`。
接下來在?`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)")
}
}
~~~
看一下?`addAlbum(_:index:)`?這個方法,先更新本地緩存,然后如果是聯網狀態還需要向服務器發送網絡請求。這便是外觀模式的強大之處:如果外部文件想要添加一個新的專輯,它不會也不用去了解內部的實現邏輯是怎么樣的。
注意:當你設計外觀的時候,請務必牢記:使用者隨時可能直接訪問你的隱藏類。永遠不要假設使用者會遵循你當初的設計做事。
運行一下你的應用,你可以看到兩個空的頁面和一個工具欄:最上面的視圖用來展示專輯封面,下面的視圖展示數據列表。
[](http://cdn3.raywenderlich.com/wp-content/uploads/2014/11/Screen-Shot-2014-11-11-at-12.33.50-AM-179x320.png)
你需要在屏幕上展示專輯數據,這是就該用下一種設計模式了:裝飾者模式。