目录
到这里,设计模式的理论部分就梳理完毕了。当前做个简要的总结:
设计原则
设计模式可以被看作是编程的一种心法或者指导原则,它们提供了在软件开发中解决常见问题的模板和最佳实践。设计模式的目的是提高代码的可维护性、可扩展性、可重用性,并降低代码的复杂性。说白了,就是为了编写高质量的代码。
贫血模型(Anemic Domain Model):
-
贫血模型将数据和业务逻辑分开。数据通常表示为纯粹的数据结构,不包含业务逻辑。
-
业务逻辑通常被放置在服务类或管理类中,而不是数据对象本身。
充血模型(Rich Domain Model):
-
充血模型将数据和业务逻辑封装在同一对象中,数据对象不仅包含数据,还包含操作数据的方法。
-
业务逻辑被视为对象的自然行为,而不是外部服务的职责。
DRY原则(Don't Repeat Yourself):
-
DRY原则强调避免代码重复。它指出在代码中不应该出现相同的逻辑、表达式或数据。
-
如果有相同的代码出现在多个地方,就应该将它提取到一个单独的地方,并通过函数、类或模块来重用。
KISS原则(Keep It Simple, Stupid):
-
KISS原则鼓励保持代码和解决方案的简单性。它强调在解决问题时应该选择最简单的方法,而不是过度复杂化。
-
简单的解决方案通常更容易理解、测试和维护。避免不必要的复杂性和过度工程。
YAGNI原则(You Aren't Gonna Need It):
-
YAGNI原则提醒开发人员不要在代码中添加不必要的功能或功能预测。只有当实际需求确实出现时才添加新功能。
-
避免不成熟的优化和过度设计,专注于当前的需求,以避免浪费时间和资源。
LOD法则(Law of Demeter,也称为迪米特法则):
-
LOD法则强调每个模块(类或对象)只应该与其直接的朋友通信,不应该与陌生人通信。朋友指的是该模块内部的成员、该模块创建的对象、该模块参数传入的对象等。
-
这有助于降低模块之间的耦合度,提高代码的可维护性。模块不应该过多地了解其他模块的内部细节。
编码规范
参考《代码整洁之道》(Clean Code)一书,一些可以改善代码质量的编程规范:
-
有意义的命名:使用具有描述性的变量名、函数名和类名,避免使用模糊或缩写的名称。
-
遵循单一职责原则:每个函数和类应该只有一个明确的职责。当一个函数做太多事情时,考虑拆分它。
-
函数短小精悍:函数应该足够短小,通常不超过20行,以提高可读性和可维护性。
-
函数参数简洁:函数的参数应尽量简洁,避免过多的参数。如果需要传递大量参数,考虑使用对象参数。
-
避免副作用:函数应该尽量避免修改全局变量或引入不必要的副作用,保持函数的纯净性。
-
提前返回:在函数中,尽早返回结果,而不是使用深度嵌套的if语句。
-
异常处理:合理处理异常情况,不要使用异常来控制程序流程。
-
统一风格:使用一致的代码风格,包括缩进、空格、命名约定等。
-
避免嵌套:避免深度嵌套的代码块,控制代码的缩进深度。
-
注释有意义:注释应该解释代码的目的和思路,而不是简单地重申代码。
-
不使用魔法数字:避免在代码中直接使用未命名的数字,使用有意义的常量或枚举值。
-
测试驱动开发(TDD):采用TDD方法编写单元测试,确保代码的正确性和可维护性。
-
代码复审:进行代码复审,让其他人审查你的代码,以发现潜在的问题和改进空间。
-
模块化和封装:将代码分解成小的、独立的模块,每个模块应该有清晰的接口和功能。
-
避免全局变量:尽量减少使用全局变量,将数据封装在适当的作用域内。
-
不要写重复代码:避免重复编写相似的代码,将重复的逻辑封装成函数或类。
-
持续学习:不断学习新的编程技巧和最佳实践,提高自己的编程水平。
-
可读性优先:代码的可读性比性能优化更重要。确保代码易于理解,然后再考虑性能问题。
-
提高抽象层次:将复杂的问题分解成简单的抽象层次,以降低复杂性。
-
保持简洁:避免不必要的复杂性和过度工程,保持代码简洁而有效。
设计模式对比
以下是一些常见的设计模式对比和总结:
-
创建型设计模式:
-
单例模式 vs. 工厂模式 vs. 抽象工厂模式:
-
单例模式用于确保一个类只有一个实例,适用于需要全局访问的对象。
-
工厂模式用于创建对象的过程,将对象的创建和使用分离。
-
抽象工厂模式是一组相关工厂方法的集合,用于创建一组相关对象。
-
-
建造者模式 vs. 原型模式:
-
建造者模式用于构建一个复杂对象,将构建过程分步进行。
-
原型模式用于复制已有对象的副本,避免了创建对象的开销。
-
-
-
结构型设计模式:
-
适配器模式 vs. 桥接模式:
-
适配器模式用于将一个接口转换成另一个接口,使得不兼容的接口能够一起工作。
-
桥接模式用于将抽象部分与其实现分离,以便它们可以独立变化。
-
-
组合模式 vs. 装饰器模式:
-
组合模式用于将对象组合成树形结构,以表示“部分-整体”的层次结构。
-
装饰器模式用于动态地给对象添加额外的行为,而不需要子类化。
-
-
代理模式 vs. 外观模式:
-
代理模式用于控制对对象的访问,可以用于懒加载、权限控制等。
-
外观模式用于提供一个简化的接口,隐藏系统的复杂性,使得客户端更容易使用。
-
-
-
行为型设计模式:
-
观察者模式 vs. 订阅-发布模式:
-
观察者模式定义了一对多的依赖关系,当一个对象状态变化时,多个观察者会收到通知。
-
订阅-发布模式(也称为事件或消息机制)类似于观察者模式,但通常使用中间件或消息队列来实现,支持异步通信。
-
-
策略模式 vs. 状态模式:
-
策略模式用于定义一组算法,使其可以相互替换,以应对不同情况下的不同需求。
-
状态模式用于将对象的状态封装成不同的状态类,以实现状态切换和行为的变化。
-
-
-
其他设计模式:
-
命令模式用于将请求和接收者解耦,以支持命令的排队、记录和撤销。
-
责任链模式用于将请求传递给一系列处理器,每个处理器决定是否处理请求或将其传递给下一个处理器。
-
访问者模式用于将数据结构和操作分离,以支持在不修改数据结构的前提下定义新的操作。
-
备忘录模式用于保存对象的状态历史,以支持撤销和恢复操作。
-
万变不离其宗
每个设计模式都应该由两部分组成:
-
第一部分是应用场景,即这个模式可以解决哪类问题;
-
第二部分是解决方案,即这个模式的设计思路和具体的代码实现。不过,代码实现并不是模式必须包含的。如果你单纯地只关注解决方案这一部分,甚至只关注代码实现,就会产生大部分模式看起来都很相似的错觉。
实际上,设计模式之间的主要区别还是在于设计意图,也就是应用场景。单纯地看设计思路或者代码实现,有些模式确实很相似,比如策略模式和工厂模式。之前讲策略模式的时候,我们有讲到,策略模式包含策略的定义、创建和使用三部分,从代码结构上来,它非常像工厂模式。它们的区别在于,策略模式侧重“策略”或“算法”这个特定的应用场景,用来解决根据运行时状态从一组策略中选择不同策略的问题,而工厂模式侧重封装对象的创建过程,这里的对象没有任何业务场景的限定,可以是策略,但也可以是其他东西。从设计意图上来,这两个模式完全是两回事儿。
最后,还是要说一句:设计模式要干的事情就是解耦。创建型模式是将创建和使用代码解耦,结构型模式是将不同功能代码解耦,行为型模式是将不同的行为代码解耦。