[设计模式]之六大设计原则

2024-08-22 15:58

本文主要是介绍[设计模式]之六大设计原则,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

就一个类而言,应该仅有一个引起它变化的原因。

假设现在要在iPhone上做一个图片编辑工具。功能有裁剪图片,旋转图片,缩放移动照片等等。

呐,我们可以写一个功能集类,然后把这些所有操作视为功能集的一部分,把代码全部写进这个类里面。

这么看来似乎可以,因为这是作为一个单独的模块嘛,把相关功能写进一个工具类里,用哪个功能调用哪个函数就好了。但这带来了一个问题就是这个工具类包含过多功能显得非常臃肿,不容易维护。而且在一个类里往往容易出现几个函数共用一个全局变量的情况,功能之间耦合度太大,难以复用。

举个最直接的例子:如果我想把这个功能移植到Android上去怎么办。这个移植过程麻烦之处并不在于语言语法变化,而是两个系统有着完全不同的手势传递机制,我要用手旋转,缩放图片这段代码完全没法复用,唯一能用的裁剪代码,也可能因为和其他代码耦合过大导致需要重新修改,退一步说,裁剪算法就算没有耦合,代码可以直接用,但关系到手势的代码对我来说都成为冗余代码,这对于代码复用就是灾难。

如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力。这种耦合会导致脆弱的设计,当变化发生时,设计会遭受到意想不到的破坏。

所以这里在设计的时候,就要考虑一下把这些功能分类。比如裁剪功能需要知道裁剪框大小,位置。那就分离出一个类,专门负责计算裁剪框四个点的坐标变化。旋转缩放图片需要知道图片的大小,缩放率,显示方向等信息,那就再分离出一个类,负责计算图片形态的变化。最后剩下手势再封装一个类,处理手势的逻辑,在不同情况下获取不同的手势数据,作为参数交给上面两个算法类进行计算输出。

这样一来,每个类的职责就变得单一了,维护就容易多了。后面再移植代码的话,算法类只需要切换语法,手势类只要去重写触发手势的条件,而不必修改逻辑。代码很快就可以改好,并且不会破坏原有的项目结构。

软件设计真正要做的许多内容,就是发现职责并把那些职责相互分离。判断是否要分离出类的方法就是,如果你能够想到多于一个的动机去改变一个类,那么这个类就具有多于一个的职责,就应该考虑类的职责分离。

优点

  • 可以降低类的复杂度,一个类只负责一项职责,其逻辑肯定要比负责多项职责简单的多
  • 提高类的可读性,提高系统的可维护性
  • 变更引起的风险降低,变更是必然的,如果单一职责原则遵守的好,当修改一个功能时,可以显著降低对其他功能的影响

里氏替换原则 Liskov Substitution Principle - LSP

子类型必须能够替换掉他们的父类型

通俗的讲,一个软件实体如果使用的是一个父类的话,那么一定适用于其子类,而且它察觉不出父类对象和子类对象的区别。即,在软件里,把父类都替换成它的子类,程序的行为没有变化。

里氏替换原则的重点在不影响原功能,而不是不覆盖原方法。

所以正常遵从该原则的处理办法是在需要覆盖父类方法时应该首先考虑使用super调用父类的同名方法以保证父类同名方法会被调用。

如果确实不需要调用父类方法,则不加此语句。

这个原则很重要,编码时要注意。

依赖倒置原则 Dependence Inversion Principle - DIP

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

通俗的说,就是要 针对接口编程,不要对实现编程 。呐,比如说电脑主板,CPU,内存,硬盘这些硬件的设计就是依赖接口设计的。单拿CPU来说,CPU有各种厂家设计的各种型号,这些型号的内部设计实现都不相同,但他们的接口是一样的,这样主板就可以随意更换CPU了。

关于倒置,比如说我有一个高层模块,模块实现对SQLite读写的功能依赖一个控制访问SQLite的低层模块。一旦我要求把SQLite改为MySQL,那这个低层模块就无法正常工作,进而导致上层模块也无法正常工作。依赖倒置就是说设计代码不再是上层依赖下层,而是两层都去依赖接口去实现,这样两层的运行状态便不会互相影响。

依赖倒转其实可以说是面向对象设计的标志,用哪种语言来编写程序不重要,如果编写时考虑的都是如何针对抽象编程而不是针对细节编程,即程序中所有的依赖关系都是终止于抽象类或者接口,那就是面向对象的设计,反之那就是过程化的设计了。

依赖倒置原则的实现可以参考策略模式: 设计模式之二:策略模式

例子中的收取现金的不同方式可以看做CPU的不同型号。调用收现金的方法可看做主板插上不同型号的CPU。就是这么个思想。

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

根据该原则,编程中要注意

  • 低层模块尽量都要有抽象类或接口,或者两者都有
  • 变量的声明类型尽量是抽象类或接口
  • 使用继承时遵循里氏替换原则

接口隔离原则 Interface Segregation Principle - ISP

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

看图,图一是未遵循该原则的结构:

 

接口隔离原则的含义是:建立单一接口,不要建立庞大臃肿的接口,尽量细化接口,接口中的方法尽量少。也就是说,我们要为各个类建立专用的接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。

接口是设计时对外部设定的“契约”,通过分散定义多个接口,可以预防外来变更的扩散,提高系统的灵活性和可维护性。

注意事项

  • 接口尽量小,但是要有限度。对接口进行细化可以提高程序设计灵活性是不挣的事实,但是如果过小,则会造成接口数量过多,使设计复杂化。所以一定要适度
  • 为依赖接口的类定制服务,只暴露给调用的类它需要的方法,它不需要的方法则隐藏起来。只有专注地为一个模块提供定制服务,才能建立最小的依赖关系
  • 提高内聚,减少对外交互。使接口用最少的方法去完成最多的事情

迪米特法则 Law Of Demeter - LOD

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

如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法,可以通过第三者转发这个调用。

迪米特法则首先强调的前提是在 类的结构设计上,每一个类应当尽量降低成员的访问权限 ,也就是要降低类之间的耦合。类之间的耦合越弱,越有利于复用,修改类相互之间的影响也会降到最低。

迪米特法则还有一个更简单的定义:只与 直接的朋友 通信。首先来解释一下什么是直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多,依赖、关联、组合、聚合等。其中,我们称出现成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。

迪米特法则的初衷是降低类之间的耦合,由于每个类都减少了不必要的依赖,因此的确可以降低耦合关系。但是凡事都有度,虽然可以避免与非直接的类通信,但是要通信,必然会通过一个“中介”来发生联系,例如本例中,总公司就是通过分公司这个“中介”来与分公司的员工发生联系的。过分的使用迪米特原则,会产生大量这样的中介和传递类,导致系统复杂度变大。所以在采用迪米特法则时要反复权衡,既做到结构清晰,又要高内聚低耦合。

开闭原则 Open Close Principle - OCP

软件实体(类,模块,函数等)应该可以拓展,但是不可修改

这个原则有两点:

  • 对于拓展是开放的 Open for extension
  • 对于更改是封闭的 Closed for modification

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

但在设计软件的时候,无论模块是多么的封闭,都会存在无法对之封闭的变化,因为你不可能在编码前就考虑到所有情况。所以在设计代码时就必须先猜测出最可能发生变化的种类,然后构造抽象来隔离变化。在编码之后,一旦遇到发生变化的地方,那就应该首先考虑要不要对这里进行结构的修改。也就是 遇到变化发生时要立即采取行动 。

比如现在在客户端类中写了一个加法程序,后来说要增加减法,那么这时就应该立即抽象出来一个运算类。虽然说直接在客户端增加减法算法很快,但考虑到以后也许会拓展更多的算法,而且代码改得越晚修改代码的范围就越大。立即修改代码结构的代价似乎比以后去改的代价要小很多。

我们希望的是在开发工作展开不久就知道可能发生的变化。查明可能发生的变化所等待的时间越长,要创建正确的抽象就越困难开放-封闭原则是面向对象设计的核心所在。遵循这个原则可以带来面向对象技术所声称的巨大好处,也就是可维护,可拓展,可复用,灵活性好。开发人员应该对程序中呈现出频繁变化的那些部分作出抽象,然而,对于应用程序中的每个部分都刻意地进行抽象同样不是一个好主意。拒绝不成熟的抽象和抽象本身一样重要。

参考

http://blog.csdn.net/zhengzhb/article/category/926691/

via: http://www.wossoneri.com/2016/05/16/[Design-Pattern]Principles/

这篇关于[设计模式]之六大设计原则的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1096725

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

怎么让1台电脑共享给7人同时流畅设计

在当今的创意设计与数字内容生产领域,图形工作站以其强大的计算能力、专业的图形处理能力和稳定的系统性能,成为了众多设计师、动画师、视频编辑师等创意工作者的必备工具。 设计团队面临资源有限,比如只有一台高性能电脑时,如何高效地让七人同时流畅地进行设计工作,便成为了一个亟待解决的问题。 一、硬件升级与配置 1.高性能处理器(CPU):选择多核、高线程的处理器,例如Intel的至强系列或AMD的Ry

基于51单片机的自动转向修复系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 单片机

SprinBoot+Vue网络商城海鲜市场的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍:CSDN认证博客专家,CSDN平台Java领域优质创作者,全网30w+

JVM内存调优原则及几种JVM内存调优方法

JVM内存调优原则及几种JVM内存调优方法 1、堆大小设置。 2、回收器选择。   1、在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提供的内存查看工具,比如JConsole和Java VisualVM。   2、对JVM内存的系统级的调优主要的目的是减少

单片机毕业设计基于单片机的智能门禁系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍程序代码部分参考 设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订

Spring的设计⽬标——《Spring技术内幕》

读《Spring技术内幕》第二版,计文柯著。 如果我们要简要地描述Spring的设计⽬标,可以这么说,Spring为开发者提供的是⼀个⼀站式的轻量级应⽤开发框架(平台)。 作为平台,Spring抽象了我们在 许多应⽤开发中遇到的共性问题;同时,作为⼀个轻量级的应⽤开发框架,Spring和传统的J2EE开发相⽐,有其⾃⾝的特点。 通过这些⾃⾝的特点,Spring充分体现了它的设计理念:在

开题报告中的研究方法设计:AI能帮你做什么?

AIPaperGPT,论文写作神器~ https://www.aipapergpt.com/ 大家都准备开题报告了吗?研究方法部分是不是已经让你头疼到抓狂? 别急,这可是大多数人都会遇到的难题!尤其是研究方法设计这一块,选定性还是定量,怎么搞才能符合老师的要求? 每次到这儿,头脑一片空白。 好消息是,现在AI工具火得一塌糊涂,比如ChatGPT,居然能帮你在研究方法这块儿上出点主意。是不

创业者该如何设计公司的股权架构

本文来自七八点联合IT橘子和车库咖啡的一系列关于设计公司股权结构的讲座。 主讲人何德文: 在公司发展的不同阶段,创业者都会面临公司股权架构设计问题: 1.合伙人合伙创业第一天,就会面临股权架构设计问题(合伙人股权设计); 2.公司早期要引入天使资金,会面临股权架构设计问题(天使融资); 3.公司有三五十号人,要激励中层管理与重要技术人员和公司长期走下去,会面临股权架构设计问题(员工股权激