欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

到底什么是设计模式

程序员文章站 2022-05-19 13:18:06
...

设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案,是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。

在 1994 年,由 Erich Gamma、Richard Helm、Ralph Johnson 和 John Vlissides 四人(这四位作者在软件开发领域里以“*”(英語,Gang of Four,简称GoF)而闻名)合著出版了一本名为 Design Patterns - Elements of Reusable Object-Oriented Software(中文译名:设计模式 - 可复用的面向对象软件元素) 的书,首次提到了软件开发中设计模式的概念。书中所提到的,总共有 23 种设计模式。

总体来说23种设计模式分为三大类:

创建型模式(Creational Patterns)(5种):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。

结构型模式(Structural Patterns)(7种):适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。

行为型模式(Behavioral Patterns)(11种):策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。

但是,设计模式的种类绝不仅仅是这23种,除此之外还有很多巧妙可爱的设计模式值得我们学习,如过滤器模式以及空对象模式。当然,我们还会讨论另一类设计模式:J2EE 设计模式。


具体如下图所示

(面试官最喜欢问的问题之一就是描述一下你最熟悉的几个设计模式)



六大原则?

不知道你们是否留意过,在不同的资料上对设计模式的六大原则也有些出入。
复制代码

(截图来自设计模式的百度百科)
复制代码

(截图来自设计模式之禅)
复制代码

(设计模式的百度百科中设计原则总起段关于面向对象的几个原则)
复制代码

当然我们不必纠结于这种问题,设计模式就是实现了以下原则,从而达到了代码复用、增加可维护性的目的,只不过是单一职责原则较少被提及。具体的介绍如下:

单一职责原则(Single Responsibility Principle,SRP)

There should never be more than one reason for a class to change.

定义: 一个类只应该有一个引起它变化的原因,也即一个类只负责一件事。像流水线作业一样,一位员工只负责自己的那一部分,完了就交给其他员工。

由来:一个类、接口或者方法如果需要实现不同的职责不利于接下去的开发和拓展。

解决:使每个类、接口、方法都非常清晰明确,利于开发和维护。

开闭原则(Open Closed Principle,OCP )

Software entities like classes,modules and functions should be open for extension but closed for modifications.

定义: 软件实体应该对扩展开放,对修改关闭。

由来:一些软件生命周期很长,必然面临维护升级等变化。而新添加的代码很容易对旧有的代码造成影响,甚至给旧有的代码带来Bug。

解决:当软件代码需要进行变动时,尽量以添加新的代码来完成,而不去修改原有的代码。也即通过扩展来完成所需要的功能的添加。

里氏替换原则(Liskov Substitution Principle,LSP)

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

定义: 继承必须确保父类所拥有的性质在子类中仍然成立。

由来:通过子类来完成父类的任务,可能会产生问题。

解决:子类可以实现父类的抽象方法,但是不去Override父类的非抽象方法。这也算是某种意义上的开闭原则吧,尽量不要去影响旧有的代码,通过扩展(取新名字,而不是Override)来完成新功能。

依赖倒置原则(Dependence Inversion Principle,DIP)

High level modules should not depends upon low level modules.Both should depend upon abstractions.Abstractions should not depend upon details.Details should depend upon abstractions.

定义: 高层模块不依赖于底层模块,两者都应该依赖于抽象,抽象不依赖于细节,细节依赖于抽象。

由来:表示层、业务逻辑层以及数据访问层之间如果分得不太清楚,各模块之间交叉调用,就会带来很强的耦合性,往往会牵一发而动全身,改动一个地方,很多地方都会受到影响,增加出错的风险。

解决:主要是通过面对接口编程,将实现细节与业务逻辑分开,它们都是通过抽象的接口来完成交互的。业务逻辑只和抽象的接口打交到,而不必关注具体的实现过程。同样实现过程也不必关注业务,它只需要关注接口即抽象即可。

接口隔离原则(Interface Segregation Principle,ISP)

The dependency of one class to another one should depend on the smallest possible interface.

定义: 客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应建立在最小接口上。

由来:一个接口里完成了很多工作,但是当个功能只需要调用接口里的一小部分功能的时候,如果调用这个接口,就会做一些不必要的工作,甚至可能产生问题。

解决:一个接口尽量完成比较单一的任务,这样两个类交互时,产生的影响才会在控制范围内。

合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)

定义:能够使用合成/聚合的,不要使用继承。合成是指局部与整体的关系;聚合则是包含的关系。

由来:继承关系是在编译时就确定了,如果想在运行时改变父类与子类的关系就不行了;另外父类改变了一定会影响到子类。继承的关系限制了更灵活地复用代码。

解决:通过使用合成/聚合来替代继承关系,达到更灵活地修改代码。

迪米特法则(Law Of Demeter || Principle of Least Knowledge,PLK)

Only talk to you immediate friends.

定义: 也称最少知道原则(Least Knowledge Principle),只和你最直接的类(成员变量、方法参数、方法返回值中的类)沟通,尽可能少地与其他实体发生交互。

由来:想降低类之间的耦合关系,相互之间尽量减少依赖关系。

解决:与越少的类相互越好,尽量做到低耦合高内聚。尽量做到模块化。

写在最后

设计模式的这几大原则是设计模式的一个根本。每一个设计模式都是为了更好的完成这些设计模式的原则而总结设计出来的。设计模式的原则是基本功,而设计模式则是对基本功的应用。设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。当你能够融会贯通的时候,就可以不用固定于设计模式了,而是根据这些设计模式的原则来*设计代码。

转载于:https://juejin.im/post/5c8865ccf265da2de04af8e1