一文带你读懂:设计模式的六大原则

面向对象六大原则详解 本文来说下面向对象六大原则 文章目录概述 概述 阅读详情

点击上方 蓝字 关注我们

软件设计最大的难题就是应对需求的变化,但是纷繁复杂的需求变化又是不可预料的,我们要为不可预料的变化做好准备,这本身是一件非常痛苦的事情,但好在有大师们已经给我们提出了非常好的六大设计原则和23种设计模式来“封装”未来的变化。

因此在学习设计模式之前,我们先回顾六大原则,它们分别是:

  • 单一职责原则(Single Responsibility Principle)

  • 开闭原则(Open Closed Principle)

  • 里氏替换原则(Liskov Substitution Principle)

  • 迪米特法则(Law of Demeter),又叫“最少知道法则”

  • 接口隔离原则(Interface Segregation Principle)

  • 依赖倒置原则(Dependence Inversion Principle)

单一职责原则

单一职责原则内涵:

单一职责原则是针对类来说的,即一个类应该只负责一项职责。

例子1:
      如类T负责两个不同职责:职责P1,职责P2。当职责P1需求变更而改变T时,可能造成职责P2发生故障,所以需要将类T的粒度分解为T1,T2。

例如,产品经理就是整理需求,程序员就是写代码,分工明确:

//产品经理
public class ProduceManager {
  //...整理需求
}
//勤奋的程序员
public class Coder {
 //...写代码
}

大白话:

一个类干好自己应该干的事情,别越界而导致业务耦合。

好处:

  1. 类的复杂性降低,实现什么职责都有清晰明确的定义;

  2. 可读性高,复杂性降低,可读性自然就提高了;

  3. 可维护性提高,可读性提高了,那自然更容易维护了;

  4. 变更引起的风险降低,变更是必不可少的,如果接口的单一职责做得好,一个接口修改只对相应的实现类有影响,对其他的接口无影响,这对系统的扩展性、维护性都有非常大的帮助。

开闭原则

开闭原则内涵:

一个软件实体,如类、模块和函数应该对扩展开放,对修改关闭。

例子2:

我们的公司里面有许许多多的程序员,无论男女都在认真的写代码。

但是有天我们的程序媛们觉得自己有“加工资的需求”。

此时,我们可以将这个动作抽象到新的接口里面,然后 FemaleCoder 去实现这个动作以完成拓展。

//公司工作                                                 
class Company{                                         
  private List<Coder> coders = new ArrayList<>();    
  void working(){                                    
    for (Coder code : coders){                     
       code.coding();                            
    }                                              
  }                                                  
}                                                      
//程序员写代码
interface Coder{
  void coding();
}
//程序媛
class FemaleCoder implements Coder{
  @Override
  public void coding() {
    //...
  }
}
//程序猿
class MaleCoder implements Coder{
  @Override
  public void coding() {
    //...
  }
}

新的接口标识“涨工资的需求”:

//待遇福利
interface Salary{
  //涨工资动作
  void raise();
}

修改新增的 FemaleCoder 类:

//程序媛
class FemaleCoder implements Coder, Salary{
  @Override
  public void coding() {
    //...
  }


  @Override
  public void raise() {
    //...我要加薪
  }
}

UML图:

大白话:

对增加新功能代码时,尽量保证不修改已有代码,然后将扩展的代码增加到项目中

好处:

  • 开闭原则非常著名,只要是做面向对象编程的,在开发时都会提及开闭原则

  • 开闭原则提高了复用性,以及可维护性

里氏替换原则

里氏替换原则内涵:

所有引用基类的地方必须能透明地使用其子类的对象。

遵循里氏替换原则,在子类中尽量不要重写和重载父类的方法。

举例子3:

我们的子类程序猿 (MaleCoder) 和程序媛(FemaleCoder) ,同继承了基类程序员(CoderPeople)。

那么凡是程序员使用的地方,无论对于程序员还是程序媛,都应该可以无缝替换。

//写代码的人
class CoderPeople {
  public void coding(){
    //...
  }
}
//程序媛
class FemaleCoder extends CoderPeople{
  @Override
  public void coding() {
    //...
  }
}
//程序猿
class MaleCoder extends CoderPeople{
}

调用点:

public class LiskovSubstitutionPrinciple {
  public static void main(String[] args) {
    //用 CoderPeople 的子类 FemaleCoder 的实例来替换 CoderPeople的实例,程序工作正常
    working(new FemaleCoder());
  }
  private static void working(CoderPeople shape){
    System.out.println("开始写代码");
    shape.coding();
    System.out.println("结束写代码");
  }
}

UML:

大白话:

里氏替换原则首先突出的是面向对象的三大特性之一:“继承”。它要求我们去遵守,是因为不遵守导致的代价太大了。

使用继承会给程序带来侵入性,程序的可移植性降低,增加对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能产生故障。

好处:

大大降低程序运行出错的概率。

接口隔离原则

接口隔离原则内涵:

客户端不应该依赖它不需要的接口;一个类对另一个类的依赖应该建立在最小的接口上。(原则中的接口,是一个泛泛而言的接口,不仅仅指Java中的接口,还包括其中的抽象类)


    举例子4:

    这个图的意思是:类A依赖接口I中的方法1,方法2,方法3,类B是对类A依赖的实现;类C依赖接口I中的方法1,方法4,方法5,类D是对类C依赖的实现。对于类B和类D来说,虽然存在用不到的方法(红色标记所示),但由于实现了接口I,所以也必须要实现这些用不到的方法。

如果接口过于臃肿,只要接口中出现的方法,不管对依赖于它的类有没有用处,实现类中都必须去实现这些方法,这显然不是好的设计。

如果将这个设计修改为符合接口隔离原则,就必须对接口I进行拆分。在这里我们将原有的接口I拆分为三个接口,拆分后的设计如图所示:

注意:

可能会觉得接口隔离原则和之前的单一职责原则很相似,其实不然。

  • 单一职责注重职责,而接口隔离原则注重对接口依赖的隔离;

  • 单一职责是约束类,其次是方法,针对的是程序中的实现和细节;而接口隔离原则约束的是接口,针对的是抽象,程序整体框架的构建。

大白话:

定义接口时要权衡考虑是否可拆分多个模块中。

使用接口时要权衡考虑是否简化实现的接口列表。

好处:

  • 使用多个专门的接口。专门的接口也就是提供给多个模块的接口。

  • 提供给几个模块就应该有几个接口,而不是建立一个臃肿庞大的接口,所有的模块都可以访问。

迪米特法则

迪米特法则内涵:

一个对象应该对其他对象有最少的了解。

迪米特原则核心观念就是:类间解耦,弱耦合。

举例子5:

这个例子中,我们知道 总公司经理 管理  总公司员工,分公司经理 管理 分公司员工。

下面的例子是符合迪米特法则的:

//总公司员工
class Employee{
  private String id;
}
//分公司员工
class SubEmployee{
  private String id;
}
//分公司经理
class SubCompanyManager{
  List<SubEmployee> subEmployees = new ArrayList<SubEmployee>();
}
//总公司经理
class CompanyManager{
  List<Employee> employeeList = new ArrayList<Employee>();
}

下面的例子是不符合迪米特法则的,因为分公司员工对于总公司经理来说,是不需要知道的类:

//总公司经理
class CompanyManager{
  //总公司员工
  List<Employee> employeeList = new ArrayList<Employee>();
  //分公司员工
  List<SubEmployee> subEmployees = new ArrayList<SubEmployee>();
}

UML:

大白话:

一个类对自己需要耦合或者调用的类知道的最少,你类内部怎么复杂,我不管,那是你的事,我只知道你有提供好的公用方法,我能正常调用即可。

依赖倒置原则

依赖倒置原则内涵:

高层模块不应该依赖低层模块,二者都应该依赖其抽象;

抽象不应该依赖细节,细节应该依赖抽象。

核心思想是面向接口编程。

举例子6:

程序员喜欢搬砖,随着年龄和经验增加,从一开始搬的普通砖头,逐渐变为银砖,到后来慢慢变为金砖...

那么分析可以知道:程序员是高层模块,而“普通砖头”、“银砖”和“金砖”都视为底层模块。

底层模块

//砖头
interface Brick{
}
//石头砖头
class StoneBrick implements Brick{
}
//银砖头
class SilverBrick implements Brick{
}
//金砖头
class GoldBrick implements Brick{
}

高层模块

//搬砖的程序员
class CoderMan{
  void movingBrick(Brick brick){
    //....
  }
}

如此一来,不管哪种砖头,程序员都可以搬了。(无论以后怎样扩展 Brick 类,都不需要再修改CoderMan 类了)

    CoderMan coderMan = new CoderMan();
    coderMan.movingBrick(new StoneBrick());
    coderMan.movingBrick(new SilverBrick());
    coderMan.movingBrick(new GoldBrick());

UML:

大白话:

依赖倒置原则的核心就是要我们面向接口编程,理解了面向接口编程,也就理解了依赖倒置。

好处:

  • 实际情况中,代表高层模块的 CoderMan 类将负责完成主要的业务逻辑,一旦需要对它进行修改,引入错误的风险极大。

  • 所以遵循依赖倒置原则可以降低类之间的耦合性,提高系统的稳定性,降低修改程序造成的风险。

总结

文章主要参考书籍有《大话设计模式》和网上一些零散的文章,写出来的目的一方面是自己对这六项原则系统地整理一下,另外也因为设计模式对编程人员来说的确非常重要,笔试面试都会用得到,希望对大家有所帮助。

往期推荐

《源码系列》

《JDK之Object 类》

《JDK之BigDecimal 类》

《JDK之String 类》

《经典书籍》

《Java并发编程实战:第1章 多线程安全性与风险》

《Java并发编程实战:第2章 影响线程安全性的原子性和加锁机制》

《Java并发编程实战:第3章 助于线程安全的三剑客:final & volatile & 线程封闭》

《服务端技术栈》

《Docker 核心设计理念》

《Kafka史上最强原理总结》

《HTTP的前世今生》

《算法系列》

《读懂排序算法(一):冒泡&直接插入&选择比较》

《读懂排序算法(二):希尔排序算法》

《读懂排序算法(三):堆排序算法》

《读懂排序算法(四):归并算法》

《读懂排序算法(五):快速排序算法》

《读懂排序算法(六):二分查找算法》

扫描二维码

获取技术干货

后台技术汇

点个“在看”表示朕

已阅

一文读懂!软件设计模式的原理与应用 本文对软件设计模式的原理及应用进行了详细阐释。原理上,单一责任、开闭、里氏替换、依赖倒置、接口隔离和迪米特法则这六大原则,分别从类的职责划分、代码扩展性、继承关系、模块依赖、接口设计及对象交互等方面,为软件设计提供了清晰准则,以增强软件的可维护性、降低耦合度。应用中,创建型、结构型、行为型模式下的多种具体模式,如单例、工厂、适配器、代理、观察者、策略模式等,各自针对不同场景,有效解决了软件设计中对象创建、结构组织及行为交互等问题,提升了软件质量。 阅读详情

相关推荐

一篇文章读懂六大设计模式

1、单例模式。2、工厂模式。3、装饰者模式。4、代理模式。5、观察者模式。6 、策略模式

lydms的博客 2829

六大原则之开闭原则

1. 开闭原则的介绍 开闭原则(Open Closed Principle)是编程中最基础、最重要设计原则 一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方)。用抽象构建框架,用实现扩展细节。 当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。 编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则。 2. 违反开闭原则示例 package com.study; public class Ocp {

小松de博客 2万+

机械臂电机力矩计算

设计 6 轴机械臂时,电机力矩计算是确保机械臂负载能力、运动精度和安全性的核心环节,需围绕和两大核心展开,结合机械臂结构参数(如关节长度、质量分布)、负载需求(如末端负载重量、惯性)和运动参数(如加速度、角速度)逐步推导。

ZPC8210的博客 1856

设计模式的六大基本原则(开闭原则、单一职责原则、里氏替换原则、接口隔离原则、依赖倒置原则、迪米特法则)

设计模式的六大基本原则(开闭原则、单一职责原则、历史替换原则、接口隔离原则、依赖倒置原则、迪米特法则)

聂可以的博客 1万+

Lm317电压源芯片制作电流源

还在找电流源芯片么?如何使用电压源芯片快速搭建电流源。

Ekko的博客 1万+

利用dxflib读写cad文件

本篇主要在qt做一个例子读取cad文件数据,使用的开源库是dxflib。用到dxflib的DL_CreationAdapter,DL_Dxf。DL_Dxf是用来读取.dxf文件的类,DL_CreatinAdapter是一个容器,当DL_Dxf加载.dxf文件后,就会响应DL_CreationAdapter这个类,读取cad数据。我们来看看...

weixin_33759269的博客 1984

七大原则——开闭原则

开闭原则的定义 开闭原则(Open Closed Principle,OCP)由勃兰特·梅耶(Bertrand Meyer)提出,他在 1988 年的著作《面向对象软件构造》(Object Oriented Software Construction)中提出:软件实体应当对扩展开放,对修改关闭(Software entities should be open for extension,but c...

m0_37654408的博客 6608

【Clickhouse从入门到精通】第51篇:ClickHouse权限管理体系详解

摘要 本文是ClickHouse权限管理系列文章的第51篇,重点解析ClickHouse RBAC权限体系中的GRANT/REVOKE机制。文章详细介绍了GRANT语句的基础语法与权限类型,包括SELECT、INSERT等常规权限以及WITH GRANT OPTION转授权功能。特别深入讲解了列级权限的实现方式,通过SELECT(col1,col2)语法实现字段粒度的访问控制,并展示了权限查询与验证方法。本文还对比了ClickHouse 20.4版本前后权限管理体系的差异,为构建安全的多租户数据平台提供了关

xyghehehehe的专栏 440

开闭原则 (Open/Closed Principle, OCP)

开闭原则是面向对象设计中的基本原则之一,通过确保软件实体对扩展开放,对修改关闭,可以提高系统的稳定性、灵活性和可维护性。在实际开发中,遵循开闭原则有助于我们设计出高质量的代码,使系统更加健壮和易于扩展。希望这个博客对你有所帮助。如果你有任何问题或需要进一步的例子,请随时告诉我!

qq_42798343的博客 3355

LPDDR4协议规范之 (四)命令和时序

LPDDR4协议规范之 (四)命令和时序命令真值表激活操作读写访问操作读前沿和后沿突发读取操作流程读操作时序写前沿和后沿突发写操作写入均衡(待更新) 命令真值表 激活操作 ACTIVATE命令由两个连续命令组成,Activate-1命令和Activate-2。通过在(Activate-1)时钟的第一个上升沿保持CS HIGH,CA0 HIGH和CA1 LOW来发出Activate-1命令,通过...

YJFeiii的博客 2万+

不同IP网段的PLC进行S7通信(PUT_GET)的具体步骤

不同IP网段的PLC进行S7通信(PUT_GET)的具体步骤 一般情况下,我们使用西门子的S7通信时都是将网络中的PLC的IP设置在同一网段,那么如果涉及到旧项目改造时,不方便修改IP地址,只能进行2个网段通信时,可以参考以下步骤: 准备条件: 2个路由器 CPU 1212C 主动连接 CPU 314C-2PN/DP 被动连接 网络搭建如下图所示: S7-1212C一侧 建立S7主动连接 ,IP地址:192.168.5.40,编写get/put 通信程序 S7-300 IP地址:192.168.0

Robot_PLC_HMI_Automation 2万+

java设计模式(2)---六大原则

单一职责原则:一个类只负责一个功能领域中的相应职责,或者可以定义为:就一个类而言,应该只有一个引起它变化的原因。单一职责原则告诉我们:一个类不能太“累”!在软件系统中,一个类承担的职责越多,它被复用的可能性就越小,而且一个类承担的职责过多,就相当于将这些职责耦合在一起,当其中一个职责变化时,可能会影响其他职责的运作,因此要将这些职责进行分离,将不同的职责封装在不同的类中,即将不同的变化原因封装在不同的类中,如果多个职责总是同时发生改变则可将它们封装在同一类中。

林知屿的博客 1773

无线充电Qi协议正向通信FSK的解调设计

常见的FSK解调方法是使用频率锁相环(PLL)来跟踪输入信号中的频率变化。PLL根据输入信号的频率变化来生成数字信号,从而实现FSK信号的解调。本文将详细介绍无线充电Qi协议正向通信FSK的解调设计,并提供相应的源代码。在上述示例代码中,我们首先定义了FSK解调的参数,包括采样率、载波频率、每个比特的持续时间和比特判定阈值。最后,通过比较滤波后的信号与比特判定阈值,我们将解调后的数字数据转换为0和1的序列。请注意,上述代码仅为示例,实际的解调设计可能需要根据具体的应用场景和系统要求进行调整和优化。

IunScala的博客 2443

设计模式六大原则

设计模式六大原则

weixin_48204844的博客 482

200、从反激到LLC:工程师的成长之路

文章摘要: 本文以工程师视角探讨从反激式到LLC电源设计的思维转变。通过48V通信电源故障案例,揭示LLC谐振电容ESR温度特性引发的隐患,强调LLC需精确计算与测试。对比反激与LLC的核心差异:反激需控制寄生参数(如漏感尖峰、电容ESR),而LLC的关键在于频率响应和死区时间优化。作者提出三大思维转变:从匝比计算转向增益曲线分析,从时域波形观察转向频域频谱诊断,从元件更换转向参数调整。最后给出实战建议,包括建立故障库、关注元件参数细节及示波器调试技巧,指出工程师需从"控制"思维升级为"谐振"思维,实现技术

Jack010169的博客 322

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

设计模式初探——六大设计原则

最近看了两本关于设计模式的书,在此记录一下感想。 第一次听说设计模式是在网上查询MVC模式的时候,顺便搜了一下设计模式,才了解到武林中存在着“23种设计模式”这么个东西。当时以为觉得设计模式就是倚天剑、屠龙刀,一个代码写的很烂的菜鸟看了设计模式就会成为“武林至尊”,代码水平立刻变得很厉害。学习了之后才知道我想错了,设计模式只是倚天剑和屠龙刀中的“九阴真经”,就算得到了还是要苦苦练习,结合实际的编...

yushuaigee的博客 331

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

看完读懂设计模式(2)-设计模式六大原则

一文读懂设计模式六大原则

2301_79351943的博客 350

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

设计模式六大原则_设计模式系列(一)

物是人非事事休,当周围的一切都发生着改变,包括我们的需求、程序等,我们又该如何去应对和解决呢?欢迎进入编程人员必经之路------设计模式1 本篇概述什么是设计模式为什么要学习设计模式怎么使用设计模式21种设计模式设计模式的遵循的六大原则设计模式之工厂模式.NET COREhttp://weixin.qq.com/r/wTikvOTEQLk-raDf923T (二维码自动识别)微信...

weixin_39683863的博客 80

设计模式设计原则

在不了解派生类的情况下,仅通过接口或基类的方法,即可清楚的知道方法的行为,而不管哪种派生类。接口隔离原则和单一职责都是为了提高类的内聚性、降低它们之间的耦合性,体现了封装的思想,但两。在抽象工厂模式中,接口是负责创建一个相关对象的工厂,而且每个工厂都能按照工厂模式提供对象。单一职责原则主要是约束类,它针对的是程序中的实现和细节;就避免了修改客户代码,如果要实现新产品直接修改工厂类,而不需要在原代码中修改,这样就降。在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,

w87859062的专栏 742

结合实例读懂设计原则

设计原则是一些基本概念和指导方针,帮助开发人员创建易于维护、可扩展和易于理解的软件

技术探索驿站 938

【9-1:读懂-设计模式】

是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结,是在不同场景下编码的最佳实践要解決的都是代码的复用性、扩展性、可读性、可维护性等问题。

leeeewwww的博客 674

设计模式--六大设计原则

最近工作不是很忙,闲下来的时间来学习下23种设计模式。工作中有时会感觉项目有新功能需要开发时,代码不好改;有时看一份新的项目代码会感觉难以阅读、不知所云,这些情况我认为可能就是开发人员写代码的时候运用的设计模式不好或者就没有注意到需要使用设计模式来提高项目的可读性和可维护性,看难以读懂不好修改的代码我想我们都会很难过。 说到可维护性,作为一个android开发,在开发初期应用一个好的设计框架也很...

gubojun的专栏 498

移动架构28_设计模式六大原二: 开闭原则

1、定义:软件的实体类, 模块, 函数应该对扩展开放, 对修改关闭; 即 软件实体应该通过扩展实现变化, 不是通过修改已有的代码实现变化;问题由来:在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已

baopengjian的专栏 578

23种设计模式

一个月学完23种设计模式

qq_36949403的博客 1419
上一篇: 一文带你读懂JDK源码:Lambda表达式
下一篇: 23天读懂23种设计模式:单例模式(创建型)
后台技术汇
博客等级 码龄11年 670粉丝 531原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后台技术汇

对你的帮助,是对我的最好鼓励。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值