假設如今有一個工具類,目的是把傳入頁面指定區域渲染成紅色swift
定義一個基類 BaseFlushedViewController: UIViewController
,返回一個 flushArea
, 供工具類進行染色。工具
class FlushHelper {
static func flush(_ viewController: BaseFlushedViewController) {
viewController.flushArea().backgroundColor = .red
}
}
class BaseFlushedViewController: UIViewController {
func flushArea() -> UIView {
return view
}
}
複製代碼
那麼咱們傳入的參數必須是他的子類,並且因爲每一個頁面可能須要刷新的視圖是不一樣的,咱們理論上應該重寫他的 flushArea
方法spa
這樣作的問題有兩個:設計
UINavigatiionController
或 UITabbarController
呢?(有可能我如今要渲染導航欄或底部標籤欄),那麼我還要再在工具類中新增兩個接口適應。這顯然不是咱們想要的class FlushHelper {
static func flush(_ viewController: BaseFlushedViewController) {
viewController.flushArea().backgroundColor = .red
}
static func flush(_ viewController: BaseFlushedNavViewController) {
viewController.flushArea().backgroundColor = .red
}
static func flush(_ viewController: BaseFlushedTabViewController) {
viewController.flushArea().backgroundColor = .red
}
}
class BaseFlushedViewController: UIViewController {
func flushArea() -> UIView {
return view
}
}
class BaseFlushedNavViewController: UINavigationController {
func flushArea() -> UIView {
return view
}
}
class BaseFlushedTabViewController: UITabBarController {
func flushArea() -> UIView {
return tabBar
}
}
複製代碼
定義一個協議code
protocol Flushable {
func flushArea() -> UIView
}
class FlushHelper {
static func flush(_ viewController: UIViewController & Flushable) {
viewController.flushArea().backgroundColor = .red
}
}
class SomeViewController: UIViewController, Flushable {
func flushArea() -> UIView {
return view
}
}
class SomeNavViewController: UINavigationController, Flushable {
func flushArea() -> UIView {
return navigationBar
}
}
class SomeFlushedTabViewController: UITabBarController, Flushable {
func flushArea() -> UIView {
return tabBar
}
}
複製代碼
將工具類的接口統一成 UIViewController & Flushable
對象
這樣作的好處:繼承
flushArea
方法,不存上文提到的在繼承以後忘記重寫的狀況UIViewController
及其子類。不須要工具類再開放額外的接口看起來面向接口的方法和使用基類的方法相比,只是工具類中的接口統一成了一個。但實際上,面向接口的方法中,SomeNavViewController
和 SomeFlushedTabViewController
都是 UIViewController
的一種特例。而使用基類的實現方法中,三種 Base
類則是平級的基類,是爲了覆蓋全部的頁面類型。接口
假設若是有一種新的導航頁面,那麼面向基類的方法,就還要去新增一個新的基類覆蓋這個特例,面向接口的則只須要擴展出一個新的類型便可,工具類接口不須要新增。it
以上的思想,就是面向對象設計規則中 開閉原則的一種體現(如有錯誤歡迎指正)。io