前言
目前正在出一个设计模式专题
系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~
本节给大家讲一下设计模式
基本概念,它的基本原则以及有哪些设计模式~
本专题的所有案例代码主要以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)设计模式,它们是:
- 单例模式(Singleton Pattern)
- 工厂方法模式(Factory Method Pattern)
- 抽象工厂模式(Abstract Factory Pattern)
- 建造者模式(Builder Pattern)
- 原型模式(Prototype Pattern)
- 适配器模式(Adapter Pattern)
- 桥接模式(Bridge Pattern)
- 组合模式(Composite Pattern)
- 装饰器模式(Decorator Pattern)
- 外观模式(Facade Pattern)
- 享元模式(Flyweight Pattern)
- 代理模式(Proxy Pattern)
- 责任链模式(Chain of Responsibility Pattern)
- 命令模式(Command Pattern)
- 解释器模式(Interpreter Pattern)
- 迭代器模式(Iterator Pattern)
- 中介者模式(Mediator Pattern)
- 备忘录模式(Memento Pattern)
- 观察者模式(Observer Pattern)
- 状态模式(State Pattern)
- 策略模式(Strategy Pattern)
- 模板方法模式(Template Method Pattern)
- 访问者模式(Visitor Pattern)
- 除此之外,还有一个常见的设计模式,被称为
依赖注入模式(Dependency Injection Pattern)
。它的作用是将依赖关系从代码中移除,通过配置文件或其他方式来注入依赖,从而使得代码更加灵活、可扩展和易于测试。
当面试官问你,你了解过哪些设计模式,脑海中你能想到哪些呢?别再回答只知道工厂模式
了~
结束语
本节内容还是有点多的,需要好好理解,下节用代码将上述的设计模式带着大家过一遍,希望大家能在理解的基础上,在工作中合理的运用设计模式去好好设计我们的代码~
本着把自己知道的都告诉大家,如果本文对您有所帮助,点赞+关注
鼓励一下呗~
Kafka 专题学习
- 一起来学kafka之Kafka集群搭建
- 一起来学kafka之整合SpringBoot基本使用
- 一起来学kafka之整合SpringBoot深入使用(一)
- 一起来学kafka之整合SpringBoot深入使用(二)
- 一起来学kafka之整合SpringBoot深入使用(三)
项目源码(源码已更新 欢迎star⭐️)
ElasticSearch 专题学习
- 利用docker搭建es集群
- 一起来学ElasticSearch(一)
- 一起来学ElasticSearch(二)
- 一起来学ElasticSearch(三)
- 一起来学ElasticSearch(四)
- 一起来学ElasticSearch(五)
- 一起来学ElasticSearch(六)
- 一起来学ElasticSearch(七)
- 一起来学ElasticSearch(八)
- 一起来学ElasticSearch(九)
- 一起来学ElasticSearch(十)
- 一起来学ElasticSearch之整合SpringBoot(一)
- 一起来学ElasticSearch之整合SpringBoot(二)
- 一起来学ElasticSearch之整合SpringBoot(三)
项目源码(源码已更新 欢迎star⭐️)
往期并发编程内容推荐
- Java多线程专题之线程与进程概述
- Java多线程专题之线程类和接口入门
- Java多线程专题之进阶学习Thread(含源码分析)
- Java多线程专题之Callable、Future与FutureTask(含源码分析)
- 面试官: 有了解过线程组和线程优先级吗
- 面试官: 说一下线程的生命周期过程
- 面试官: 说一下线程间的通信
- 面试官: 说一下Java的共享内存模型
- 面试官: 有了解过指令重排吗,什么是happens-before
- 面试官: 有了解过volatile关键字吗 说说看
- 面试官: 有了解过Synchronized吗 说说看
- Java多线程专题之Lock锁的使用
- 面试官: 有了解过ReentrantLock的底层实现吗?说说看
- 面试官: 有了解过CAS和原子操作吗?说说看
- Java多线程专题之线程池的基本使用
- 面试官: 有了解过线程池的工作原理吗?说说看
- 面试官: 线程池是如何做到线程复用的?有了解过吗,说说看
- 面试官: 阻塞队列有了解过吗?说说看
- 面试官: 阻塞队列的底层实现有了解过吗? 说说看
- 面试官: 同步容器和并发容器有用过吗? 说说看
- 面试官: CopyOnWrite容器有了解过吗? 说说看
- 面试官: Semaphore在项目中有使用过吗?说说看(源码剖析)
- 面试官: Exchanger在项目中有使用过吗?说说看(源码剖析)
- 面试官: CountDownLatch有了解过吗?说说看(源码剖析)
- 面试官: CyclicBarrier有了解过吗?说说看(源码剖析)
- 面试官: Phaser有了解过吗?说说看
- 面试官: Fork/Join 有了解过吗?说说看(含源码分析)
- 面试官: Stream并行流有了解过吗?说说看
推荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)
- springboot-all
地址
: github.com/qiuChenglei…- SpringBoot系列教程合集
- 一起来学SpringCloud合集
- SpringCloud整合 Oauth2+Gateway+Jwt+Nacos 实现授权码模式的服务认证(一)
- SpringCloud整合 Oauth2+Gateway+Jwt+Nacos 实现授权码模式的服务认证(二)
博客(阅读体验较佳)