面向对象编程(OOP)是一种编程范式,它使用“对象”来设计应用程序和程序的结构。OOP的核心概念包括封装、继承和多态性。近年来,随着函数式编程的兴起,OOP似乎有些失宠。函数式编程以其纯函数和不可变性等特点受到推崇,但OOP仍然有其独特的价值和应用场景。
OOP的核心在于模拟现实世界中的实体和它们之间的交互。现实世界充满了对象,而不是线性函数。虽然函数可以处理复杂的逻辑,但它们通常不擅长表达现实世界的模糊性和复杂性。
OOP通过定义“做什么”(接口/抽象类)和“怎么做”(具体类)来构建系统。它将系统分解为定义交互的契约和执行操作的实现。在现实世界和OOP中,对象通过基于用例和正常行为的一组可定义的条件进行交互,并将异常行为作为异常返回。
电话系统是一个简单但功能强大的例子。尽管技术发生了巨大变化,但电话的用例在过去100年里保持不变。
打电话的人拨打一个号码,接收者接听电话,他们交谈,然后一方挂断电话。这是一个基本的简单系统!
尽管技术发生了巨大变化,现代智能手机今天仍然可以呼叫墙壁上的人工辅助电话,反之亦然。
为什么这能行得通?因为世界由实现接口(继承)的对象组成,具有特定的功能(封装)。一些设备随着微小的变化而演变,例如脉冲拨号电话演变为触摸音调电话(多态性)。
这个关键系统不仅由三个接口定义,而且这些接口本身非常简单。如果听说过“保持简单,愚蠢”这个词,那么这就是这个说法的典范。这个系统在过去100多年里基本上保持不变。所要做的就是填补空白!
系统最基础的部分是ITelephone。这是打电话的人或接收者用来交谈的,这是整个系统的基本用例。
电话网络最初是由打电话的人拿起扬声器,点击杠杆几次,并与操作员合作,他们会将电话从网络路由到网络,直到接收者的电话响起。这很粗糙,但有效。
今天,打电话的人拿起扬声器,触摸一些数字,计算机计算出最有效的路线到接收者,接收者的电话就会响起。
在过去的100年里,ITelephone、ITelephoneNetwork和IRoute都随着技术的变化而演变,但这并不重要。ITelephone已经从一个扬声器和点击器变成了一个复杂的手持计算机,它恰好也参与电话通话。向后兼容性是这种演变的标志。ITelephone接口强制执行这组通用的可用操作和接收器,以便任何ITelephone的实例都可以与任何ITelephoneNetwork的实例通过位于设备之间的适配器进行通信,这些适配器处理不同技术之间的转换。
ITelephoneNetwork定义了电话路径上每个网络之间的基本通信。同样,适配器填补了技术空白,但它们只是将一种技术翻译成另一种技术。
可以通过一个(非常)简单的活动图来查看这些用例的交互。
真的可以这么简单吗?三个接口真的可以描述所有这些吗?是的,是的,他们可以。当然,每个操作的细节在这里没有反映出来,但它们也不相关。请注意,在这一点上,还没有创建一个类。已经定义了用例、接口和电话通话期间发生的活动。在这一点上,可能会忍不住立即开始创建那些实现,但首先让定义这些接口如何相互作用,用一个序列图。
这里定义了很多工作,实现仍然不重要。
序列图从左到右,从上到下读取。每条线代表方法、事件或返回值。这里的一切都是在接口中,接口中的一切都在这里。序列与实现用例的活动相匹配。100年来,各种技术实现了这个序列,每一步都不在乎下一个实现。
在大多数书籍和文章中,会看到一个系统的具体实现。会有旋转电话、触摸音调电话、手机和智能手机。会有操作员将电线插入面板,计算机数字化地路由电话。会看到铜网络、光纤网络、蜂窝网络和数字网络。不会在这里看到这些实现。为什么?
因为它们不重要。