什么是设计模式?
在此分享下个人拙见,文章有点长,需要静下心来慢慢看,或者去WX公众号点击上方的听书↑
学习设计模式需要具备的基础知识
-
熟悉一门面向对象的编程语言
-
理解面向对象的三大特性,尤其是
多态
-
能看懂UML的类图
本文就以下几点进行展开
什么是设计模式
如果将代码的设计和编写比喻为搭积木,那就像搭建一座精美的建筑一样。每一块积木代表着代码中的一个组件、类或函数,它们拥有不同的形状、功能和特性。通过巧妙地组合和搭建这些积木,我们可以构建出一个结构良好、稳固可靠
的软件系统。
在搭积木的过程中,我们需要考虑每一块积木的作用和位置,确保它们能够恰如其分地组合在一起,形成一个完整的整体。高内聚的积木可以使得代码更易于理解和维护
,而低耦合的积木则可以增加系统的灵活性
和可扩展性
。
而且,就像搭积木一样,编写代码也需要一定的技巧和经验。有时候,我们需要尝试多种组合方式,才能找到最合适的解决方案。而且,随着项目的进行,我们可能会不断地调整和优化代码的结构
,就像不断地拆除和重新搭建积木一样。
设计模式是面向对象程序设计的一种便于升级和维护的软件设计思想
,是通过抽象和概念来描述通用的解决方案
。它们提供了一种在面对特定问题
时的最佳实践方法
,并帮助开发人员更好地组织和设计他们的代码
。设计模式的目的是为了降低依赖、降低耦合、提高代码的可重用性、可维护性和可扩展性,以便于升级和维护系统,及提高软件系统的质量和性能。
设计模式不是简单地将一个固定的代码框架套用到项目中,而是一种严谨的编程思想
,旨在提供解决特定问题的经验和指导。
设计模式的目的
对设计模式的目的特性的一些简述
-
降低耦合度: 设计模式通过定义清晰的接口和抽象层次,有助于降低系统中各个组件之间的耦合度。
-
可维护性: 衡量系统在修改、修复错误或者进行其他维护工作时的难易程度。设计模式通过提供
清晰的结构和组织方式
,开发人员更容易理解系统的结构和设计意图,这有助于团队协作和代码维护
,使得系统更易于理解和维护。每个设计模式都解决特定类型的问题,使得系统的各个部分更易于单独修改、测试和维护。 -
可扩展性: 衡量系统在面对不断增长的需求或者负载时,能够有效地扩展性能和容量的能力。一个具有良好可扩展性的系统能够灵活地扩展到满足不同规模的需求,而不会影响系统的性能和稳定性。
-
可重用性: 衡量系统中的组件、模块或者代码能够被有效地重复利用的程度。这也是代码模块化、高内聚低耦合带来的特性。这有助于减少重复造轮子,提高开发效率、降低开发成本,并且有助于保持代码的一致性和稳定性。当某个模块成长壮大,有可能就被造成"轮子",方便日后使用。
-
可读性: 通过使用常见的设计模式,可以让其他开发者更容易理解代码的意图和结构,使得代码更
易于理解和维护
。可读性是可维护性的基础。 -
可测试性: 通过将系统分解为可测试的模块,并使用设计模式来构建这些模块,使得系统更易于进行单元测试、集成测试和自动化测试。可以减少测试的复杂度和成本。可测试性也是可维护性的基础。
-
系统质量: 衡量系统在设计、开发、测试和部署等方面的质量水平,包括功能完整性、可靠性、安全性、可用性、一致性等方面。良好质量的系统能够满足用户的需求,并且能够在长期运行中保持稳定和可靠。
-
系统性能: 衡量系统在执行任务时的速度、响应时间、吞吐量和资源利用率等方面的表现。性能良好的系统能够快速地响应用户请求,并且能够在高负载下保持稳定的性能表现。
面向对象设计的原则
设计模式的核心思想是面向对象编程(OOP)的延伸,面向对象设计的原则同样也就适用于设计模式,也称为设计模式的原则,这些原则有助于创建可维护、灵活和可扩展的软件系统。
- 单一职责原则 (Single Responsibility Principle, SRP):
设计目的单一的类,一个类应该只负责一项职责
。
- 开放-关闭原则 (Open/Closed Principle, OCP):
软件实体(类、模块、函数等)应该对扩展开放,对修改关闭
。这意味着在不修改现有代码的情况下,可以通过扩展现有代码来引入新的功能。
- 里氏替换原则 (Liskov Substitution Principle, LSP):
子类型
必须能够替换
其基类型
。在使用继承时,子类必须能够替代父类而不影响程序的正确性。LSP 是继承复用的基石,只有当派生类可以替换掉基类,且软件单位的功能不受到影响时,基类才能真正被复用,而派生类也能够在基类的基础上增加新的行为。
- 接口分离原则 (Interface Segregation Principle, ISP):
一个类不应该被强迫实现它用不到的接口,使用多个专门的接口
比使用单个的总接口要好。
- 依赖反转原则 (Dependency Inversion Principle, DIP):
较高抽象层次的类永远不应该依赖于较低抽象层次的类,两者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象
。
以上设计原则是面向类与类
单个包的,除此之外,以下六种面向对象设计原则是面向类与包
和包与包
的关系
- 重用发布等价原则 (Reuse/Release Equivalence Principle,REP):
组件的发布单位应该是与其重用单位相等的。这意味着,对于经常一起使用的代码,应该被组织到一个共同的组件中,以便可以一起发布和重用
。
- 共同封闭原则 (Common Closure Principle,CCP):
将那些一起变化的类放在同一个包中,这样,它们就可以被同时修改并一起发布。这个原则强调了类之间的关联性和紧密度。
- 共同重用原则 (Common Reuse Principle,CRP):
将那些一起被重用的类放在同一个包中,这样,类和包就可以被一起重用。这个原则强调了代码重用的组织和管理。
- 无环依赖原则 (Acyclic Dependencies Principle,ADP):
软件包之间的依赖关系不应该形成环路,即不应该存在循环依赖的情况。
- 稳定依赖原则 (Stable Dependencies Principle,SDP):
软件包应该依赖于比它更稳定的包。这意味着,高层次的模块应该依赖于低层次的模块,并且不应该反过来。
- 稳定抽象原则 (Stable Abstractions Principle,SAP):
软件包的抽象程度应该与其稳定性保持一致。具体来说,稳定的包应该是抽象的,而不稳定的包应该是具体的。
我们在使用其他开发者开源的jar包时,其jar包常常依赖了很多其他jar包,这些类与包
和包与包
之间的依赖,遵循的是后6种设计原则,否则在后续的jar包更新迭代中将很难做到包的稳定、重用、依赖包兼容性等。一般开发只需要掌握前五种原则,后六种原则知道理解即可,也许以后用得到。
这些原则是面向对象设计的基石,它们强调代码的灵活性、可维护性和可扩展性等。通过遵循这些原则,开发人员可以创建更加稳定和易于维护的软件系统。这些原则并不是固定的规则,具体的应用需要根据实际情况和项目需求进行权衡和取舍。
设计模式分类
设计模式分为创建型、结构型和行为型三大类设计模式:
-
创建设计模式都是关于
对象实例化
; -
结构设计模式都是关于
类和对象的组合
; -
行为设计模式关注算法和对象之间
职责的分配
。
根据上述对分类的简述,要做到见名之意
。
创建、结构和行为设计模式还可以进一步细分为类模式
和对象模式
,在软考考试中必考的一个点
。
创建设计模式
创建设计模式都是关于对象实例化。类创建模式
在实例化过程中使用继承 改变被实例化的类;而对象创建模式
将实例化委派 给另一个对象 。
-
工厂方法模式:创建多个派生类(子类)的实例;
-
抽象工厂模式:创建多个类系列的实例;
-
生成器模式:将复杂对象的构建与其表示形式分离;
-
单例模式:保证一个类仅有一个实例,并提供一个全局访问点;
-
原型模式:通过克隆(调用
Object.clone()
)现有对象来创建新对象。
结构设计模式
结构设计模式都是关于类和对象的组合
。结构型类模式
使用继承来组合接口和实现;而结构型对象模式
使用对象进行组合,以获得新功能的方法。
-
适配器模式:匹配接口,使不兼容的接口可以在一起工作;
-
桥接模式:将对象的接口与其实现分离,使它们都可以独立地变化;
-
组合模式:将对象组合成树形结构;
-
装饰模式:动态地给对象添加新功能;
-
外观模式:提供了一个简单的接口,用于访问复杂子系统中的一组接口;
-
享元模式:使用共享对象来减少内存占用和提高性能;
-
代理模式:其他对象通过代理对象来访问目标对象,起到控制目标对象的访问效果。
行为设计模式
行为设计模式关注算法和对象之间职责的分配
。这些模式主要涉及到对象之间的通信、责任分配和算法的抽象。行为类模式
使用继承机制在类间分派行为;而行为对象模式
使用对象间相互协作。
-
责任链模式:通过将请求沿着处理对象的链传递;
-
命令模式:将请求封装为对象,
-
解释器模式:用于将语言的语法解析成具体的操作;
-
迭代器模式:按顺序访问集合的元素;
-
中介者模式:定义简化类之间的通信行为;
-
备忘录模式:捕获和恢复对象的内部状态;
-
观察者模式:被观察的对象被修改时,会自动通知依赖它的对象;
-
状态模式:在对象的状态更改时更改对象的行为;
-
策略模式:将算法封装在类中,允许在运行时选择算法的行为;
-
模板方法模式:定义算法骨架,将一些步骤留给子类实现具体细节;
-
访问者模式:定义对类的新操作而不进行更改。
设计模式的选择(简述)
什么时候考虑使用设计模式?设计模式怎么选择?
你总不会在编写1+1=几的代码时使用设计模式。不要把简单的问题复杂化,简单的问题往往可以通过面向对象程序设计的特性去解决,比如多态、抽象等。
是否需要使用设计模式应该根据具体的项目需求、团队成员的技能水平、项目的预期寿命周期、问题的复杂度、系统的需求、团队的能力以及项目的规模。设计模式是一种解决问题的思想工具,可以帮助提高代码的质量和可维护性,但并不是适用于所有情况的银弹。编写的程序应该以满足设计模式的目的特性
的方向去考虑,尽管你并没有使用设计模式也好,比如以满足面向对象的三大特性
、面向抽象编程
等方式去编写程序。总言之,根据项目问题,以设计模式的目的和原则为导向
去权衡是否需要使用设计模式。
根据特定的设计问题和设计要点来选择设计模式。比如:考虑对象的创建和管理的问题,大范围就是选择创建型设计模式,再根据具体要求选择其大类下的细分类型,比如需要确保一个类仅有一个实例,那么就选择单例模式
。
如果别人写的代码像是几十年没人住的房子布满了错综复杂的蜘蛛网一样,那么你改起来就会不停的问候他人,以至于嘴角都有了泡沫。
这两个问题一篇文章的几段话很难讲明白,等设计模式这个系列写完后,再就这两个问题展开讲讲个人拙见,但可以知道的是,设计模式的学习可以提高编程能力
、编程思想
和软件系统设计能力
等等。
总结
设计模式不是简单地将一个固定的代码框架套用到项目中,而是一种严谨的编程思想
,旨在提供解决特定问题的经验和指导。设计模式的目的
是为了降低依赖、降低耦合、提高代码的可重用性、可维护性和可扩展性,以便于升级和维护系统,及提高软件系统的质量和性能。
掌握前人总结的编程设计原则和已有的设计模式的编程思想,作为提升个人编程能力的一门基础课
,在面对复杂问题时,能够经过自己的独立思考后更好地解决问题。
WXGzh回复:设计模式
,即可获取对应的思维导图,后续有关设计模式的新资料都可以从这个入口获取到。