热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

架构与设计模式的六大原则

编程是一个先思考再编码的过程,思考是优于编码技能的,在思考过程中我们会考虑代码的可重用性、可靠性、更容易被他人理解,这时就会使用到设计模式让代码编写工程化,这篇文章整理了设计模式的

编程是一个先思考再编码的过程,思考是优于编码技能的,在思考过程中我们会考虑代码的可重用性、可靠性、更容易被他人理解,这时就会使用到设计模式让代码编写工程化,这篇文章整理了设计模式的六大原则。


1. 单一职责原则

单一职责原则(Single Responsibility Principle)

There should never be more than one reason for a class to change.(有且仅有一个原因可以引起类的变更)

不管让我干啥,我都只干一件事,你让我下楼取快递,顺便将垃圾带下去,对不起,我不干,我只取快递。

优点:


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

  • 可读性提高,复杂性降低,那当然可读性提高了;

  • 可维护性提高,可读性提高,那当然更容易维护了;

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


2. 接口隔离原则

接口隔离原则(Interface Segregation Principle)

1、Clients should not be forced to depend upon interfaces that they don't use.(客户端不应该依赖它不需要的接口)

2、The dependency of one class to another one should depend on the smallest possible interface.(类间的依赖关系应该建立在最小的接口上)

举个例子,类A 通过 Interface1 依赖类B,方法1,方法2,方法3;类B 通过 Interface1 依赖D,方法1,方法4,方法5,看下未使用接口隔离原则和使用了接口隔离原则发生了什么变化。


3. 依赖倒置原则

依赖倒置原则(Dependence Inversion Principle)

1、High level modules should not depend upon low level modules.Both should depend upon abstractions. (高层模块不应该依赖低层模块,两者都应该依赖其抽象)

2、Abstractions should not depend upon details. (抽象不应该依赖细节)

3、Details should depend upon abstractions. (细节应该依赖抽象)

举个例子,类A 直接依赖 类B,假如要将 类A 改为依赖 类C,则必须通过修改 类A 的代码来达成。这种场景下,类A一般是高层模块,负责复杂的业务逻辑;类B 和类C 是低层模块,负责基本的原子操作;假如修改类A,会给程序带来不必要的风险。

解决方案:将 类A 修改为依赖 接口Interface1,类B 和 类C 各自实现 接口Interface1,类A 通过 接口Interface1 间接与 类B 或者 类C 发生联系,则会大大降低修改 类A 的几率。


4. 里氏替换原则

里氏替换原则(Liskov Substitution Principle)

1、If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.(如果对每一个类型为 S 的对象o1,都有类型为 T 的对象 o2,使得以 T 定义的所有程序 P 在所有的对象 o1 都代换成 o2 时,程序 P 的行为没有发生变化,那么类型 S 是类型 T 的子类型)

2、Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.(所有引用基类的地方必须能透明地使用其子类的对象)

举个例子,有一功能 P1,由 类A 完成,现需要将功能 P1 进行扩展,扩展后的功能为 P,其中 P 由原有功能 P1 与新功能 P2 组成,新功能 P 由 类A 的 子类B 来完成,则 子类B 在完成新功能 P2 的同时,有可能会导致原有功能 P1 发生故障。

解决方案:当使用继承时,遵循里氏替换原则。类B 继承 类A 时,除添加新的方法完成新增功能 P2 外,尽量不要重写 父类A 的方法,也尽量不要重载父类A的方法。

继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定一系列的规范和契约,虽然它不强制要求所有的子类必须遵从这些契约,但是如果子类对这些方法任意修改,就会对整个继承体系造成破坏,而里氏替换原则就是表达了这一层含义。

继承作为面向对象三大特性之一,在给程序设计带来巨大便利的同时,也带来了弊端。比如使用继承会给程序带来侵入性,程序的可移植性降低,增加了对象间的耦合性,如果一个类被其他的类所继承,则当这个类需要修改时,必须考虑到所有的子类,并且父类修改后,所有涉及到子类的功能都有可能会产生故障。

优点:


  • 代码共享,减少创建类的工作量,每个子类都拥有父类的方法和属性;

  • 提高代码的重用性,可扩展性。

  • 提高产品或项目的开放性。


5. 迪米特法则

迪米特法则(Law of Demeter)

1、Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.(每个单元对于其他的单元只能拥有有限的知识:只是与当前单元紧密联系的单元)

2、Each unit should only talk to its friends; don't talk to strangers.(每个单元只能和它的朋友交谈:不能和陌生单元交谈)

3、Only talk to your immediate friends.(只和自己直接的朋友交谈)

举个例子,我们通过 手机 阅读 微信读书 APP 内的 书籍,如何设计类的编写?

手机类 和 书籍类,这两个不能直接发生调用关系,需要 手机类 和 微信读书 APP 类先发生调用关系,然后微信读书 APP 类 再和 书籍 类可以发生调用关系,这样才遵循迪米特法则。


6. 开闭原则

开闭原则(Open Closed Principle)

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.(软件中的对象(类,模块,函数等等)应该对于扩展是开放的,但是对于修改是封闭的)

在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改时,可能会给旧代码中引入错误,也可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。

解决方案:当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化。


小结


  • 单一职责原则告诉我们实现类要职责单一;

  • 接口隔离原则告诉我们在设计接口的时候要精简单一;

  • 依赖倒置原则告诉我们要面向接口编程;

  • 里氏替换原则告诉我们不要破坏继承体系;

  • 迪米特法则告诉我们要降低耦合;

  • 开闭原则是总纲,告诉我们要对扩展开放,对修改关闭;

转载:架构与设计模式的六大原则 



推荐阅读
  • 本文介绍了在解决Hive表中复杂数据结构平铺化问题后,如何通过创建视图来准确计算广告日志的曝光PV,特别是针对用户对应多个标签的情况。同时,详细探讨了UDF的使用方法及其在实际项目中的应用。 ... [详细]
  • 本文详细介绍了如何将After Effects中的动画相机数据导入到Vizrt系统中,提供了一种有效的解决方案,适用于需要在广播级图形制作中使用AE动画的专业人士。 ... [详细]
  • 构建Python自助式数据查询系统
    在现代数据密集型环境中,业务团队频繁需要从数据库中提取特定信息。为了提高效率并减少IT部门的工作负担,本文探讨了一种利用Python语言实现的自助数据查询工具的设计与实现。 ... [详细]
  • 本文详细介绍了如何在本地环境中安装配置Frida及其服务器组件,以及如何通过Frida进行基本的应用程序动态分析,包括获取应用版本和加载的类信息。 ... [详细]
  • 为什么会崩溃? ... [详细]
  • 本文简要介绍了如何使用 Python Elasticsearch DSL 进行基本和高级查询,包括连接 Elasticsearch、执行简单和复杂查询、聚合、排序及分页等。 ... [详细]
  • 最新进展:作为最接近官方声明的信息源,本文吸引了大量关注。若需获取最新动态,请访问:lkhill.com/ccie-version-5-update ... [详细]
  • 本文详细介绍了利用JavaScript实现的五种不同的网页弹出窗口技术,包括全屏窗口、全屏模式窗口、带收藏链接工具栏的窗口、网页对话框及HTA窗口。 ... [详细]
  • A1166 峰会区域安排问题(25分)PAT甲级 C++满分解析【图论】
    峰会是指国家元首或政府首脑之间的会议。合理安排峰会的休息区是一项复杂的工作,理想的情况是邀请的每位领导人都是彼此的直接朋友。 ... [详细]
  • 本文介绍了进程的基本概念及其在操作系统中的重要性,探讨了进程与程序的区别,以及如何通过多进程实现并发和并行。文章还详细讲解了Python中的multiprocessing模块,包括Process类的使用方法、进程间的同步与异步调用、阻塞与非阻塞操作,并通过实例演示了进程池的应用。 ... [详细]
  • 本文详细解析 Skynet 的启动流程,包括配置文件的读取、环境变量的设置、主要线程的启动(如 timer、socket、monitor 和 worker 线程),以及消息队列的实现机制。 ... [详细]
  • 本文探讨了在使用Apache HttpClient 4.x(作为commons-httpclient 3.x的后续版本)时,如何配置默认的HttpContext,以确保每次执行请求时无需显式传递上下文。 ... [详细]
  • Kubernetes 实践指南:初次体验
    本文介绍了如何通过官方提供的简易示例,快速上手 Kubernetes (K8S),并深入理解其核心概念和操作流程。 ... [详细]
  • 前端技术分享——利用Canvas绘制鼠标轨迹
    作为一名前端开发者,我已经积累了Vue、React、正则表达式、算法以及小程序等方面的技能,但Canvas一直是我的盲区。因此,我在2018年为自己设定了一个新的学习目标:掌握Canvas,特别是如何使用它来创建CSS3难以实现的动态效果。 ... [详细]
  • Kubernetes Services详解
    本文深入探讨了Kubernetes中的服务(Services)概念,解释了如何通过Services实现Pods之间的稳定通信,以及如何管理没有选择器的服务。 ... [详细]
author-avatar
飞松安步当车9_U
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有