一起来学设计模式之认识设计模式

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: 前言目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~本节给大家讲一下设计模式基本概念,它的基本原则以及有哪些设计模式~本专题的所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整吧~设计模式初识设计模式是一种经过验证的、被广泛应用的解决特定问题的软件设计方案,它提供了一种在软件设计中反复使用的解决方案。设计模式通常描述了一个问题的情境、解决方案和解决方案的优点和缺点。设计模式不是一种具体的编程语言特性或库,而是一种通用的设计思想和方法。

前言

目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~

本节给大家讲一下设计模式基本概念,它的基本原则以及有哪些设计模式~

本专题的所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整吧~

设计模式初识

设计模式是一种经过验证的、被广泛应用的解决特定问题的软件设计方案,它提供了一种在软件设计中反复使用的解决方案。设计模式通常描述了一个问题的情境、解决方案和解决方案的优点和缺点。设计模式不是一种具体的编程语言特性或库,而是一种通用的设计思想和方法

设计模式的出现是为了解决软件设计中的一些常见问题,如代码重复、可维护性、灵活性和扩展性等。设计模式可以帮助开发人员更加高效地设计软件,使得软件结构更加清晰、易于维护和扩展。

如此之看,设计模式显得尤为重要, 平时我们自己都在强调编程思想是多么重要,可是到了自己写代码的时候,又是大量的if/else, switch/case自己都觉得很low。或许大家都听过设计模式或者学过一些,但是都不知道咋应用到自己的代码里,本专题将会结合一些实际案例给大家讲解如何合理运用设计模式来改善我们的代码质量。

本文偏理论一些,需要耐心揣摩,当面试官问你这些原则的时候,主要考察大家对设计模式的理解~

设计模式 & 七大原则

学好设计模式,首当其冲的是要对理论有一个充分的理解,光学是不够的,这样显得很脆弱,很多同学在学设计模式的时候,都在关注代码的,模仿代码结构,换一个业务场景就歇菜了。首先学习的观念要改一下,我希望大家学的时候,边学边带着问题去思考,为什么这么设计,帮我解决了什么问题,我平时写的代码哪部分可以用这个设计模式进行改写?当你有足够多的意识的时候,想必对设计模式会有一个更好的理解~

废话说的有点多,下面来看有哪些原则:

单一职责原则

单一职责原则是指一个类或模块应该只有一个职责,即一个类或模块只应该有一个引起它变化的原因。

这个原则可以帮助开发者更好地组织代码结构,使得每个类或模块的职责更加清晰,更加易于维护和扩展。如果一个类或模块承担了过多的职责,那么当其中任意一个职责发生变化时,就可能会影响到其他职责,从而导致代码的不稳定性和难以维护。

实践单一职责原则可以使得代码更加具有可读性和可维护性,也能提高代码的复用性。在实际编码中,可以通过以下方式来实现单一职责原则:

  • 将类或模块的职责分离:将一个职责过多的类或模块拆分成多个类或模块,每个类或模块只承担一个职责。
  • 降低类或模块之间的耦合性:避免不必要的依赖关系,尽量使用接口或抽象类来定义类或模块之间的通信方式,以降低它们之间的耦合性。
  • 对类或模块进行抽象和封装:将类或模块中的通用功能抽象出来,形成一个单独的模块,使得这些通用功能可以在多个类或模块中被复用。

里氏替换原则

里氏替换原则是面向对象设计中的一个基本原则,它是由Liskov提出的,因此也被称为Liskov Substitution Principle(LSP)。这个原则定义为:所有引用基类的地方必须能够透明地使用其子类的对象,即子类必须能够替换掉它们的父类

这个原则的核心思想是:子类应该可以替换父类并且能够在不影响程序正确性的情况下,增加新的行为(方法)

如果一个类违反了里氏替换原则,那么在使用这个类时,可能会引入一些意想不到的行为或结果,导致系统出现错误或异常。因此,遵守里氏替换原则可以使得代码更加灵活、可扩展和易于维护。

遵循里氏替换原则的实现方式如下:

  • 子类必须实现父类的所有抽象方法,或者说子类必须可以完全替换父类。
  • 子类可以有自己的方法,但是不能影响父类原有的行为。
  • 子类的方法可以有自己的特殊实现,但是必须满足父类的前置条件、后置条件和约束条件。

总之,里氏替换原则提醒我们在继承时需要注意,不要破坏原有的程序功能和逻辑,尽量使用接口、抽象类和组合等方式来达到代码的灵活性和可扩展性。

依赖倒置原则

依赖倒置原则(Dependency Inversion Principle,DIP)是面向对象设计中的一个重要原则,其核心思想是高层模块不应该依赖底层模块,它们应该依赖于抽象接口(或抽象类)。同时,抽象接口也不应该依赖于具体实现,而是具体实现应该依赖于抽象接口。

依赖倒置原则主要通过以下方式来实现:

  • 通过抽象类或接口来定义公共的行为。
  • 高层模块不应该直接依赖于具体实现类,而是应该依赖于抽象接口。
  • 具体实现类应该实现对应的接口,而不是继承抽象类。

依赖倒置原则的好处是能够降低代码的耦合度提高代码的灵活性可维护性。当需要改变某个模块的具体实现时,只需要改变具体实现类而不需要改变高层模块的代码,这样可以减少代码的改动范围,提高代码的可维护性和扩展性。

除此之外,依赖倒置原则还可以帮助我们更好地实现“面向接口编程”,提高代码的可读性和可理解性。

接口隔离原则

接口隔离原则(Interface Segregation Principle,ISP)是面向对象设计中的一个基本原则,其核心思想是:客户端不应该依赖于它不需要的接口。该原则的目标是降低类之间的耦合度,使得类更加灵活、可扩展和易于维护。

接口隔离原则要求我们设计精简、高内聚的接口,一个类不应该强制性地依赖于它不需要的方法。换言之,我们应该将一个大的接口拆分成多个小的接口,每个接口只包含一组相关的方法,这样可以减少类与类之间的依赖关系,降低代码的耦合度,提高代码的灵活性和可扩展性。

接口隔离原则可以通过以下几个方面来实现:

  • 将一个大的接口拆分成多个小的接口,每个接口只包含一组相关的方法。
  • 接口中的方法应该是客户端需要的,不要强制客户端实现不需要的方法。
  • 将接口尽可能地抽象化,避免暴露细节,保持接口的简洁性。
  • 接口设计应该满足“单一职责原则”,即每个接口只有一个职责。

总之,接口隔离原则是面向对象设计中非常重要的一个原则,它能够有效地降低代码的耦合度,提高代码的灵活性和可维护性。遵循接口隔离原则可以使得代码更加清晰、简洁、易于理解和扩展。

迪米特法则

迪米特法则(Law of Demeter,LoD),也称为最少知识原则(Least Knowledge Principle,LKP),是面向对象设计中的一个重要原则,其核心思想是:一个对象应该对其他对象保持最少的了解,它只需要和它直接的朋友交流。这个朋友指的是该对象的成员变量、方法参数、方法返回值等。

迪米特法则的主要目的是降低系统的耦合度,提高系统的可维护性和可扩展性。该原则要求我们在设计系统时,遵循以下两个原则:

  • 只和直接的朋友通信:一个对象只应该和它直接的朋友(成员变量、方法参数、方法返回值等)交流,不应该向外暴露更多的信息。
  • 不要向外暴露过多的细节:一个对象的实现细节不应该暴露给外部,只需要向外提供必要的接口就可以了。

迪米特法则可以通过以下几个方面来实现:

  • 合理设计类之间的关系,避免出现过于紧密的耦合关系。
  • 将复杂的业务逻辑封装到一个单独的类中,对外只提供必要的接口。
  • 将接口尽可能地抽象化,避免暴露细节,保持接口的简洁性。

迪米特法则的好处是可以有效地降低系统的耦合度,提高系统的可维护性和可扩展性。当系统的模块之间的耦合度降低时,修改一个模块对其他模块的影响也会降低,从而提高了系统的灵活性和可维护性。同时,迪米特法则还可以帮助我们更好地实现“面向接口编程”,提高代码的可读性和可理解性。

开闭原则

开闭原则(Open-Closed Principle,OCP)是面向对象设计中的一个基本原则,其核心思想是:一个软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。这意味着我们应该通过增加新的功能来扩展软件实体的功能,而不是通过修改现有的代码来实现。

开闭原则的主要目的是降低软件的维护成本,提高软件的可扩展性和可复用性。如果一个软件实体不遵循开闭原则,那么每次添加新功能都需要修改已有的代码,这样会增加系统的复杂性,降低系统的可维护性和可扩展性。

开闭原则可以通过以下几个方面来实现:

  • 使用抽象化和多态来实现扩展:通过定义抽象的接口和实现类,利用多态机制来实现扩展,可以避免修改已有的代码。
  • 使用接口而非实现类进行编程:在编程时尽量使用接口而不是具体的实现类,这样可以避免依赖于具体的实现,提高代码的可扩展性。
  • 使用设计模式:使用设计模式(如策略模式、模板方法模式等)可以帮助我们更好地遵循开闭原则,提高代码的可维护性和可扩展性。

开闭原则的好处是可以有效地降低软件的维护成本,提高软件的可扩展性和可复用性。遵循开闭原则可以使得代码更加清晰、简洁、易于理解和扩展,同时也可以提高代码的可读性和可理解性

组合/聚合复用原则

组合/聚合复用原则(Composite/Aggregate Reuse Principle,CARP)是面向对象设计中的一个基本原则,其核心思想是:优先使用组合/聚合关系来达到代码复用的目的,而不是继承关系

组合关系指的是包含和被包含的关系,例如一个部门包含多个员工;而聚合关系指的是整体和部分的关系,例如一家公司由多个部门组成。在组合/聚合关系中,一个对象通常作为另一个对象成员变量存在,通过对成员变量的组合或聚合来实现代码的复用。

相比于继承关系,组合/聚合关系具有更大的灵活性和可扩展性。使用组合/聚合关系可以使得代码更加清晰、简洁、易于维护和扩展,同时也可以避免继承带来的副作用,如父类的修改可能会影响所有的子类。

组合/聚合复用原则可以通过以下几个方面来实现:

  • 优先使用组合/聚合关系来实现代码复用:在设计类之间的关系时,优先考虑使用组合/聚合关系来实现代码复用,而不是使用继承关系。
  • 将公共的功能抽象成接口:将公共的功能抽象成接口,通过组合/聚合关系来实现代码复用,并使用接口来描述公共的功能。
  • 避免使用继承关系实现代码复用:避免在设计中过度使用继承关系,因为继承关系可能会导致代码的耦合性增加,同时也会限制代码的可扩展性和可维护性。

组合/聚合复用原则的好处是可以使得代码更加灵活、可扩展、易于维护和理解。使用组合/聚合关系可以避免继承带来的副作用,同时也可以提高代码的可读性和可理解性。

24大设计模式

在面向对象编程中,常用的23种设计模式被称为GOF(Gang of Four)设计模式,它们是:

  1. 单例模式(Singleton Pattern)
  2. 工厂方法模式(Factory Method Pattern)
  3. 抽象工厂模式(Abstract Factory Pattern)
  4. 建造者模式(Builder Pattern)
  5. 原型模式(Prototype Pattern)
  6. 适配器模式(Adapter Pattern)
  7. 桥接模式(Bridge Pattern)
  8. 组合模式(Composite Pattern)
  9. 装饰器模式(Decorator Pattern)
  10. 外观模式(Facade Pattern)
  11. 享元模式(Flyweight Pattern)
  12. 代理模式(Proxy Pattern)
  13. 责任链模式(Chain of Responsibility Pattern)
  14. 命令模式(Command Pattern)
  15. 解释器模式(Interpreter Pattern)
  16. 迭代器模式(Iterator Pattern)
  17. 中介者模式(Mediator Pattern)
  18. 备忘录模式(Memento Pattern)
  19. 观察者模式(Observer Pattern)
  20. 状态模式(State Pattern)
  21. 策略模式(Strategy Pattern)
  22. 模板方法模式(Template Method Pattern)
  23. 访问者模式(Visitor Pattern)
  24. 除此之外,还有一个常见的设计模式,被称为依赖注入模式(Dependency Injection Pattern)。它的作用是将依赖关系从代码中移除,通过配置文件或其他方式来注入依赖,从而使得代码更加灵活、可扩展和易于测试。

当面试官问你,你了解过哪些设计模式,脑海中你能想到哪些呢?别再回答只知道工厂模式了~

结束语

本节内容还是有点多的,需要好好理解,下节用代码将上述的设计模式带着大家过一遍,希望大家能在理解的基础上,在工作中合理的运用设计模式去好好设计我们的代码~

本着把自己知道的都告诉大家,如果本文对您有所帮助,点赞+关注鼓励一下呗~

Kafka 专题学习

项目源码(源码已更新 欢迎star⭐️)

ElasticSearch 专题学习

项目源码(源码已更新 欢迎star⭐️)

往期并发编程内容推荐

推荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)

博客(阅读体验较佳)


 

相关文章
|
4月前
|
设计模式 算法 Java
C++设计模式
C++设计模式
17 0
|
4月前
|
设计模式 数据中心
常用设计模式这样学
常用设计模式这样学
|
7月前
|
设计模式 安全 Java
设计模式之单列模式
设计模式之单列模式
31 0
|
9月前
|
设计模式
我所认识的设计模式
我所认识的设计模式
39 0
|
9月前
|
设计模式 算法 程序员
【3W2H设计模式】什么是设计模式
【3W2H设计模式】什么是设计模式
167 0
|
10月前
|
设计模式
设计模式思考总结
设计模式思考总结
42 0
|
12月前
|
设计模式 Java
23种设计模式
23种设计模式
117 0
|
设计模式 存储 安全
设计模式(三)
设计模式
116 0
|
设计模式 XML 存储
|
存储 设计模式 XML
设计模式(六)
设计模式
159 0