关于软件设计的两三事:我们为什么需要设计模式
“
人生苦短,不如养狗
作者:闲宇非鱼
一、前言

上图中分别展示了没有使用设计模式的代码和使用了设计模式的代码。那么,屏幕前的你觉得哪个代码在编写上会更好呢?
哈喽,我是闲宇。相信所有使用过面向对象编程语言进行开发的朋友们,一定对设计模式这样一门非常经典的编程技巧不会陌生。但同时我也相信并不是所有人都喜欢这样一门编程技巧。那么到底是什么原因导致在开发者态度迥异的情况下,设计模式依然能经久不衰、流行至今。今天我们就来具体聊一聊:我们为什么需要设计模式?
二、什么是设计模式?
在探讨为什么之前,我们需要先解决一下另一个问题:什么是设计模式?
设计模式其实是GoF这四位编程大佬基于长期实践的经验和面向对象编程语言的特性,针对某类典型业务逻辑问题或场景提出的可复用方案,也即我们经常说的最佳实践方案。
简单来说,设计模式就像是软件编程中的”独孤九剑“,它为开发者在编程领域提供了一整套通用的设计思想和解决方案,让开发者能够更好地去组织自己的代码来实现提高代码的可复用性、可扩展性以及可维护性的目的。用说人话的方式来翻译一下他们的目的就是:不改代码 > 新增模块代码 > 只改动其中一个模块的代码 > 改动所有模块的代码。为了实现这样的目的,就必须依赖继承与多态这两个非常重要的编程语言特性。这也就意味着设计模式只能运用在面向对象编程的编程语言中。
需要强调的是,设计模式是一种代码编写逻辑上的设计思想和解决方案,无关乎算法,也无关乎架构设计。这也就意味着,引入设计模式即不会带来程序性能上的提升,也不会对软件架构有任何的改善。
三、设计模式为什么不受待见?
讲到这里,想必有一些朋友已经能够感受到设计模式某些不受待见的地方了。那么,下面我们就来具体看下设计模式有哪些为人诟病的问题。
第一点,使用设计模式会使编程过程变得复杂。很多推崇设计模式的开发人员认为使用设计模式会让代码变得优雅,但这种优雅并不是没有代价的。从文章最一开始两段代码的对比我们不难看出,使用设计模式会在很大程度上降低代码编写的简洁程度。很多时候一个简单的业务逻辑如果只使用if-else这类基本的逻辑处理只需要几行或者十几行的代码就能够实现,但套用了设计模式之后,十几行的代码就有可能会演变成包含几百行代码的复杂结构。这在无形之中增加了不少让人使用它的心理负担。特别是当你在项目组中还遇到了喜欢在各种地方都要套用设计模式的开发搭档时,这种心理负担会变得更加沉重。
第二点,使用设计模式会降低代码的可读性。这个问题其实是上一个问题的延伸,编写都这么复杂了,阅读就更不要谈了。毕竟对于一个正常人类来说,相比需要在各种类和接口中各种跳转寻找正确的执行逻辑,直接、明确且易于理解的代码结构肯定更加受欢迎。
第三点,设计模式无法带来程序性能上的提升。这一点在之前介绍设计模式时就已经提到过,设计模式本质上是一种代码编写逻辑上的设计思想。从它的实际落地方案上我们可以看到,引入设计模式会导致原本直接的调用逻辑变为多层级间的调用,这种编写上的调整不仅不会对程序性能带来提升,反而会带来额外的内存占用以及执行效率的降低。这对于不少追求程序性能的开发人员来说是相当难以接受的。
三、为什么需要设计模式?
既然设计模式存在着这样或者那样的问题,那我们为什么还要使用设计模式呢?
让我们重新回顾一下GoF四人组提出的设计模式的初心:借助设计模式来提高代码的可复用性、可扩展性与可维护性。
基于这样的指导思想,我们不难得出这样的分析:实际上,设计模式解决的是在遇到需要多人协同开发,并且项目中存在着复杂但可以模块化处理的业务逻辑的场景时可能出现的编码混乱和冗余的问题,也就是说,它解决的是代码编写的问题。设计模式就像一个经过精心设计的大纲,将这些复杂的业务逻辑分门别类地放置在不同的模块之中,每个开发者只需要在自己负责的对应模块中编写或调整对应的业务逻辑,极大程度上避免了各种业务逻辑代码混杂在一块时可能出现的“牵一发而动全身”的混乱情况。
讲到这里,相信大家应该能够明白这样一个道理:对于设计模式来说,代码的简洁、直观以及程序执行的性能永远不会是第一优先级需要保证的,如何提升代码的可复用、可扩展以及可维护才是它最核心的任务,或者说是唯一的任务。在弄明白了这一点之后,你会发现设计模式中给出的通用解决方案其实并不重要,只要我们掌握了设计模式的核心思想,我们完全可以按照实际的业务场景来创造更加适合的解决方案,不必拘泥于书中给出的那些模式。
其实在绝大部分的开发场景中,在项目的起步阶段,很少会引入设计模式,因为此时的业务逻辑非常简单,使用设计模式完全属于大炮打蚊子,成本和收益完全不对等。只有当业务发展到一定程度后,在业务逻辑的复杂度不断提升的情况下,为了更好地进行复杂逻辑的处理和扩展,避免在后续的开发过程中产生越来越多的屎山代码和bug,才会引入设计模式对原有的代码进行重构,以避免和当前代码的“前任”以及其他“现任”出现冲突和碰撞,让这些代码能够和谐、独立地相处。
当然,要想实现这样一个和谐的场景,所有参与编写代码的现任,呃,开发人员都需要熟练掌握设计模式的使用技巧。否则,现任碰面的修罗场大概会直接燃爆整个项目代码。
夜雨聆风