我是靠谱客的博主 柔弱小虾米,这篇文章主要介绍iOS 遵循开闭原则的实际案例讨论,现在分享给大家,希望可以做个参考。

案例:

假设现在有一个工具类,目的是把传入页面指定区域渲染成红色

不好的设计

定义一个基类 BaseFlushedViewController: UIViewController,返回一个 flushArea, 供工具类进行染色。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
class FlushHelper { static func flush(_ viewController: BaseFlushedViewController) { viewController.flushArea().backgroundColor = .red } } class BaseFlushedViewController: UIViewController { func flushArea() -> UIView { return view } } 复制代码

那么我们传入的参数必须是他的子类,而且由于每个页面可能需要刷新的视图是不同的,我们理论上应该重写他的 flushArea 方法

这样做的问题有两个:

  • 新建的页面类可能会忘记重写该方法
  • 如果需要传入的页面是一个 UINavigatiionControllerUITabbarController呢?(有可能我现在要渲染导航栏或底部标签栏),那么我还要再在工具类中新增两个接口适应。这显然不是我们想要的
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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 } } 复制代码

面相接口的设计

定义一个协议

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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 及其子类。不需要工具类再开放额外的接口

比较

看起来面向接口的方法和使用基类的方法相比,只是工具类中的接口统一成了一个。但实际上,面向接口的方法中,SomeNavViewControllerSomeFlushedTabViewController 都是 UIViewController 的一种特例。而使用基类的实现方法中,三种 Base 类则是平级的基类,是为了覆盖所有的页面类型。

假设如果有一种新的导航页面,那么面向基类的方法,就还要去新增一个新的基类覆盖这个特例,面向接口的则只需要扩展出一个新的类型即可,工具类接口不需要新增。

以上的思想,就是面向对象设计规则中 开闭原则的一种体现(若有错误欢迎指正)。

转载于:https://juejin.im/post/5caf4e916fb9a068ab40ab2d

最后

以上就是柔弱小虾米最近收集整理的关于iOS 遵循开闭原则的实际案例讨论的全部内容,更多相关iOS内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(59)

评论列表共有 0 条评论

立即
投稿
返回
顶部