假设如今有一个工具类,目的是把传入页面指定区域渲染成红色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