实战设计模式之简介

软件的复杂性

软件的复杂性是一个很宽泛的概念,任何使软件难以理解、难以修改、难以维护的东西,都属于软件的复杂性。软件复杂的根本原因是:变化。这里的变化,包括:客户需求的变化、技术平台的变化、开发团队的变化、市场环境的变化等。

IBM院士、IBM研究院软件工程首席科学家Grady Booch曾经说过下面这段话,有助于我们理解软件的复杂性和需求变化的随意性。

"建筑商从来不会去想给一栋已建好的100层高的楼房底下再新修一个小地下室------这样做花费极大而且注定要失败。然而令人惊奇的是,软件系统的用户在要求作出类似改变时却不会仔细考虑,而且他们认为这只是需要简单编程的事。"

为什么需要设计模式

随着软件复杂性的增加、项目规模的急剧增大,代码的组织、维护和扩展性成为了一项挑战。面对这些挑战,开发者们逐渐总结出了一些最佳实践和通用解决方案,也就是这里提到的"设计模式"。设计模式并不是具体的算法实现或数据结构,而是解决问题的一种模板或蓝图。设计模式描述了如何在特定情况下构建对象和类之间的关系,以解决常见的架构问题。

设计模式描述了在我们周围不断重复发生的问题,以及该问题的解决方案的核心。这样,你就能一次又一次地使用该解决方案而不必重复劳动。设计模式实际上就是类与相互通信的对象之间的组织关系,包括它们的角色、职责、协作方式等各个方面。

设计模式通常和面向对象编程结合起来使用。面向对象设计模式是"好的面向对象设计",所谓"好的面向对象设计"是指那些可以满足 "应对变化,提高复用"的设计。现代软件设计的特征是:需求频繁变化。设计模式的要点是:寻找变化点,然后在变化点处应用设计模式,从而来更好地应对需求的变化。

解决复杂性

设计模式最大的优势在于:抵御变化。为什么能抵御变化呢?原因在于其遵循了以下的设计原则。

单一职责原则:一个类只负责一个职责,只有一个引起它变化的原因。

开放封闭原则:对于功能扩展是开放的,对于修改是封闭的。

里斯替换原则:子类可以替换基类,继承必须确保超类所拥有的性质在子类中仍然成立。

依赖倒置原则:高层次的模块不应该依赖于低层次的模块,它们都应该依赖于抽象。抽象不应该依赖于具体,具体应该依赖于抽象。

接口隔离原则:一个类对另一个类的依赖应该建立在最小的接口上。

迪米特法则:一个对象应当对其他对象有尽可能少的了解,不和陌生人说话。

封装变化点:使用封装来创建对象之间的分界层,让设计者可以在分界层的一侧进行修改,而不会对另一侧产生不良的影响,从而实现层次间的松耦合。

优先使用对象组合,而不是类继承:类继承通常为"白箱复用",对象组合通常为"黑箱复用"。继承在某种程度上破坏了封装性,子类父类耦合度高。而对象组合则只要求被组合的对象具有良好定义的接口,耦合度低。

设计模式的圣经

提起设计模式,就不得不提《设计模式------可复用面向对象软件的基础》这本经典著作。1995年,GOF(Gang Of Four),也就是Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides这四个人,合作出版了《Design Patterns: Elements of Reusable Object-Oriented Software》一书,被奉为设计模式的"圣经"。

该书描述了23种经典的面向对象设计模式,确立了模式在软件设计中的地位,开创了一种新的面向对象设计思潮。从此,参与设计模式研究的人数呈现爆炸性的增长。

总结

使用设计模式时,一定要区分需求的稳定部分和可变部分。一个软件必然有稳定部分,这个部分就是核心业务逻辑。如果核心业务逻辑发生变化,软件就没有存在的必要,核心业务逻辑是我们需要固化的。对于可变的部分,需要判断可能发生变化的程度来确定设计策略和设计风险。考虑你的设计中什么可能会发生变化,考虑你允许什么发生变化而不让这一变化导致重新设计。设计模式的核心在于发现变化点,并封装之。另外,一种可变性不应散落在代码的很多角落,一种可变性也不应当与另一种可变性混合在一起。

在实际工作中,很少会规定必须使用哪些设计模式,这样只会带来限制和条条框框。不能为了使用设计模式而去做架构,而是有了做架构的需求后,发现它符合某一类设计模式的结构,再将两者结合。设计模式从来都不是单个设计模式独立使用的。在实际应用中,通常多个设计模式混合使用,你中有我,我中有你。设计模式要活学活用,不要生搬硬套。死记硬背是没用的,还要从实践中理解。想要游刃有余地使用设计模式,需要打下牢固的程序设计语言基础,夯实自己的编程思想,积累大量的时间经验,提高开发能力。

设计模式解决的是设计不足的问题,但同时也要避免设计过度。一定要牢记简洁原则,要知道设计模式是为了使设计简单,而不是更复杂。如果引入设计模式使得设计变得复杂,只能说我们把简单问题复杂化了,问题本身不需要设计模式。设计模式的应用不宜先入为主,一上来就使用设计模式是对设计模式的最大误用。没有一步到位的设计模式。敏捷软件开发实践提倡的"Refactoring to Patterns"(重构获得模式),是目前普遍公认的最好的使用设计模式的方法。

或许有的人会说,我们不需要设计模式,我们的系统很小,设计模式会束缚我们的实现。实际上,设计模式体现的是一种思想,而思想则是指导行为的一切。理解和掌握了设计模式,并不是说记牢了23种或更多的设计场景和解决策略,实际接受的是一种思想的熏陶和洗礼。等这种思想融入到了你的思想中后,你就会不自觉地使用这种思想去进行你的设计和开发,而这才是最重要的。

相关推荐
数据与后端架构提升之路10 分钟前
Seata 全景拆解:AT、TCC、Saga 该怎么选?告别“一把梭”的架构误区
分布式·架构
檐下翻书17323 分钟前
在线绘制水流量示意图
论文阅读·架构·毕业设计·流程图·论文笔记
漂洋过海的鱼儿3 小时前
设计模式——EIT构型(三)
java·网络·设计模式
搞科研的小刘选手3 小时前
【数字经济专题会议】第三届粤港澳大湾区数字经济与人工智能国际学术会议(DEAI 2026)
人工智能·aigc·软件工程·电子商务·数字经济·经济学·学术会议
dajun1811234563 小时前
油气能源开采工艺流程示意图绘制
信息可视化·架构·流程图·能源
Asher阿舍技术站4 小时前
【5G无线接入技术系列】四、无线接口架构
5g·架构
青火coding4 小时前
SOFAServerless架构的意义
java·运维·中间件·架构·serverless
檐下翻书1735 小时前
免费在线工艺流程图制作工具_生产/化工/食品工艺流程绘制模板
人工智能·金融·架构·流程图·论文笔记·pcb工艺
程序员泠零澪回家种桔子7 小时前
MCP架构核心组件
人工智能·ai·架构
Trouvaille ~7 小时前
【Linux】进程间通信(二):命名管道与进程池架构实战
linux·c++·chrome·架构·进程间通信·命名管道·进程池