面向协议与面向对象的区别

来源:互联网 发布:linux schedule 编辑:程序博客网 时间:2024/06/05 00:08

面向对象的设计和面向协议的设计都使用了多态让我们使用同样的接口来跟不同的类型进行交互。在面向对象的设计中,我们使用了基类提供的接口来跟所有的子类进行交互。在面向协议的设计中,我们使用了协议和协议扩展提供的接口来跟遵守该协议的类型进行交互。

两种设计方式写出的代码都很好而且易懂。但个人感觉协议/协议扩展代码更好,因为协议/协议扩展的方法整体更干净和易懂些。

当我们谈到面向协议编程的时候应该从协议开始构思而不是从基类开始。然后我们可以使用协议扩展来为遵守该协议的类型添加功能,而对于面向对象编程,我们还得从基类开始。

在面向协议设计中我们更多的使用了值类型(结构体struct)而非引用类型(类class)。Apple已经说了我们应该在合适的地方尽可能地偏好使用值类型而非引用类型。
【struct与class的区别会在下一篇博客中讲到】

协议/协议扩展相比基类有 3 个优点:

第一个优点是类型可以遵守多个协议而只能拥有一个基类。这意味着我们可以创建很多个协议以添加每个特定的功能而不是把所有功能都写到一个巨大的类中。例如,使用一个的 People 协议,我们还能创建包含特定需求和功能的 Teacher、Fireman、和 Doctor 协议。然后,English Teacher 和 Surgery Doctor 类型会遵守 People、Teacher 和 Doctor 协议。使用基类, 我们需要把定义在 People、Teacher 和 Doctor 协议中的功能组合到单个巨大的超类中。这种类如果足够庞大也常被称为上帝类,容易造成遍地bugs的后果,耦合度太高。

第二个优点是我们不需要源代码就可以使用协议扩展来添加功能。这意味着我们可以扩展任何协议,即使是 Swift 自己内建的协议也能扩展。而给超类添加功能我们需要知道源代码。我们可以使用扩展给超类添加功能,这意味着所有的子类会继承那个功能。然而,我们一般使用扩展来为特定的类添加功能而非为类的层级添加功能。

第三个优点是协议可以被类、结构体和枚举遵守,而类层级被约束为类类型。协议/协议扩展让我们可以在尽可能合理的地方使用值类型

面向协议编程的例子更易懂而且更安全。在面向对象编程的例子中,所有的属性都定义在基类中。我们需要查看基类的代码或文档来看看基类中定义了哪些属性,并且这些属性是怎么定义的。使用协议,我们也需要查看协议自身或协议的文档来查看要实现的属性,但是实现是在类型自身中做的。这允许我们在类型自身中查看所实现的所有东西而不需要来回查看超类的代码,或者穿梭于类的层级来查看东西是怎么实现和初始化的。

子类中的构造函数也必须调用基类的构造函数以确保基类的所有属性都被合理地设置了。虽然这的确保证了子类之间初始化的一致性,但是它也隐藏了类是如何初始化的。在面向协议的例子中,所有的初始化都是在类型自身中完成的。因此,我们不需要在类的层级之间来回穿梭以查看所有东西是如何初始化的。

Swift 中的基类提供了我们要求的实现。Swift中的协议仅仅是一个约定,任何遵守给定协议的类型必须填充协议指定的需求。因此,使用协议,所有的属性、方法和构造函数都被定义在遵守协议的类型自身中。这让我们很容易地查看到所有东西是怎么被定义和初始化的。

很明显面向协议的目的是为了降低代码的耦合性。 比如说几个类有一些共同点,那么以前我可能会让他们继承同一个父类,再这个父类中去实现他们共同的部分,但是实际的事物往往是一系列特质的组合,而不单单是以一脉相承并逐渐扩展的方式构建的。以后慢慢会发现面向对象很多时候其实不能很好地对事物进行抽象,我们可能需要寻找另一种更好的方式。

1.代码清晰,便于维护和阅读
2.组件化模块化,降低类之间的耦合
3.代码规范化,面向协议的代码几乎如同写了readme一般,他把一些类通过协议归纳到一块,各个类却又是相互独立的。对于大型项目价值很大。

总而言之,面向协议相对于面向对象来说更具有可伸缩性和可重用性,并且在编程的过程中更加模块化,通过协议以及协议扩展替代一个庞大的基类,这在大规模系统编程中会有很大的便捷之处。

原创粉丝点击