多态对一个软件架构师的重要性

简介: 面试经常会被问到的题目之一,面向对象的三大特征是什么?多态则是三大特征之一,个人认为三大特征中最为重要的,另外的两大特征是封装和继承。为什么说多态对软件架构师非常重要,对系统软件非常重要呢?举个例子,当软件面向一个客户的时候,你会发现软件写得很简单,很快就能满足其需求。随着时间的推移,软件面向的不再是一个客户。每个客户提出的需求千差万别,尤其当出现针对性的、个性化的需求。软件的迭代、升级会变得相对困难,拓展功能变得困难。

面试经常会被问到的题目之一,面向对象的三大特征是什么?多态则是三大特征之一,个人认为三大特征中最为重要的,另外的两大特征是封装和继承。

为什么说多态对软件架构师非常重要,对系统软件非常重要呢?举个例子,当软件面向一个客户的时候,你会发现软件写得很简单,很快就能满足其需求。随着时间的推移,软件面向的不再是一个客户。每个客户提出的需求千差万别,尤其当出现针对性的、个性化的需求。软件的迭代、升级会变得相对困难,拓展功能变得困难。

然而,多态很好的帮助我们解决该问题。多态对源代码的依赖关系具有很好的控制能力,这种能力让软件架构师可以构建出插件式架构,让高层策略性组件与底层实现性组件分离,底层组件可以被编译成插件,实现独立于高层组建的开发和部署。

也就是说当我们很好的运用多态,有三大优势:

1、控制源代码的依赖关系;
2、组件独立部署能力;
3、组件独立开发能力;

Robert C. Martin 在《整洁架构之道》中很好的阐述了多态的强大性,今天我们来学习一下。

以下:

依赖反转

我们可以想象一下在安全和便利的多态支持出现之前,软件是什么样子的。下面有一个典型的调用树的例子,main 函数调用了一些高层函数,这些高层函数又调用了一些中层函数,这些中层函数又继续调用了一些底层函数。在这里,源代码层面的依赖不可避免地要跟随程序的控制流。


image.png

图:源代码依赖与控制流的区别

如你所见,main 函数为了调用高层函数,它就必须能够看到这个函数所在的模块。在 C 中,我们会通过 #include 来实现,在Java 中则通过 import 来实现。而在 C#中则用的是 using 语句。总之,每个函数的调用都必须要引用被调用放所在的模块。
显然,这样做就导致了我们在软件架构上别无选择。在这里,系统行为决定了控制流,而控制流则决定了源代码依赖关系。

当我们使用了多态,情况就不一样了。

image.png

图:依赖反转

如你所见,模块 HL1 调用 ML1 模块中的 F() 函数,这里的调用是通过源代码级别的接口来实现的。当函数在程序实际运行时,接口这个概念是不存在的,HL1 会调用 ML1 的 F() 函数。

模块 ML1 和接口 I 在源代码上的依赖关系或者叫继承关系,该关系的方向和控制流正好是相反的,这就是依赖反转。这种反转对软件架构设计的影响非常大。

事实上,通过利用面向对象编程语言所提供的这种安全便利的多态实现,无论我们面对怎样的源代码级别的依赖关系,都可以将其反转。

通过这种方法,软件架构可以完全控制采用了面向对象这种编程方式的系统中所有的源代码依赖关系,而不再受到系统控制流的限制。不管哪个模块调用或者被调用,软件架构师都可以随意更改源代码依赖关系。

接下来我们看一个案例:典型的系统分为用户层、业务层、数据库。通常我们的依赖关系是用户层 Controller 调用业务的 Service,业务层调用数据库层 DAO 或者资源库 Repository。


image.png

图:数据库和用户界面都依赖于业务逻辑

这意味着我们让用户界面和数据库都成为业务逻辑的插件。也就是说,业务逻辑模块的源代码不需要引入用户界面和数据库这两块。

这样一来,业务逻辑、用户界面以及数据库就可以编译成三个被独立的组件或者部署单元(例如 jar 文件、DLL 文件、Gen 文件等),这些组件或者部署单元的依赖关系与源代码的依赖关系是一致的,业务逻辑组件也不会依赖于用户界面和数据库这两个组件。

于是,业务逻辑组件就可以独立于用户界面和数据库来进行部署了,我们对用户界面或者数据库的修改将不会对业务逻辑产生任何影响,这些组件都可以被分别 独立部署。

简单来说,当某个组件的源代码需要修改时,仅仅需要重新部署该组件,不需要更改其他组件,这就是独立部署的能力。

如果系统中的所有组件都可以独立部署,那它们就可以由不同的团队并行开发。这就是所谓的独立开发能力。


总结

看似简单,实则大部分程序员并没将其运用到各自到系统软件中。前段时间微服务很火、DDD也很热,很多思想都离不开多态。系统软件存在的意义是解决用户问题,用户问题则是核心部分,也就是用户业务逻辑。如何有效的分离系统软件的业务逻辑,控制与业务逻辑无关的代码,从而降低软件复杂度是一名优秀的工程师或者架构师必经之路。

目录
相关文章
|
27天前
|
算法 安全
【 第十二章】软件设计师 之 面向对象设计与结构化分析设计
软件设计师 之 面向对象设计与结构化分析设计备考资料
【 第十二章】软件设计师 之 面向对象设计与结构化分析设计
|
4月前
|
设计模式 算法 Java
深入理解面向对象设计的深层原则与思维
软件设计原则是指在软件开发过程中,通过一系列指导性的原则来指导设计决策和编码实践。这些原则旨在提高软件系统的质量,使其具有可维护性、可扩展性、可重用性和可测试性。几个重要性:可维护性、可扩展性、可重用性、可测试性和降低系统复杂度。软件设计原则是提高软件系统质量和可维护性的基石。遵循这些原则可以使得代码更加清晰、灵活和可靠,提高开发效率和软件质量,减少后期维护成本。同时,它们也为团队合作和团队成员共同理解代码提供了共同的规范和指导。
124 2
深入理解面向对象设计的深层原则与思维
|
4月前
|
设计模式 存储 自然语言处理
Java面向对象设计七大原则
Java面向对象设计七大原则
97 0
|
存储 人工智能 测试技术
软工视频——面向对象技术(OOA、OOD、OOP、OOT)
面向对象的技术是当前计算机界所关心的重点,,面向对象的概念和应用已经扩展到很宽的范围,如面向对象的数据库系统、面向对象的系统分析与设计、CAD 技术、人工智能以及其他广泛的应用范围。
【C#本质论 八】类-从设计的角度去认知(多态)
【C#本质论 八】类-从设计的角度去认知(多态)
59 0
|
设计模式 测试技术 uml
面向对象设计的九大基本原则 (GRASP)
面向对象设计的九大基本原则 (GRASP)
1125 0
|
自然语言处理 搜索推荐 Java
重拾面向对象软件设计
软件设计的最大目标,就是降低复杂性,万物不为我所有,但万物皆为我用。引用 JDK 集合框架创办人 Josh Bloch 的一句话来结束。学习编程艺术首先要学会基本的规则,然后才能知道什么时候可以打破这些规则。
10908 5
重拾面向对象软件设计
|
测试技术
浅谈面向对象方法学
浅谈面向对象方法学
401 0
浅谈面向对象方法学
|
设计模式 关系型数据库 uml
OOP编程七大原则
OCP(Open-Closed Principle),开放封闭原则:软件实体应该扩展开放、修改封闭。实现:合理划分构件,一种可变性不应当散落在代码的很多角落里,而应当被封装到一个对象里;一种可变性不应当与另一个可变性混合在一起。
1201 0