软件工程设计原则

简介: 设计原则是设计模式中重要的指导。设计原则往往比设计模式更重要,真是因为设计原则的存在,才指导完成设计模式。所有的设计模式都是通过设计原则推导出来的,如果某一个设计模式违背了设计原则,那么这个模式一定是有问题的。


依赖倒置原则 (DIP)

高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定)。

抽象(稳定)不应该依赖于实现细节(变化),实现细节(变化)应该依赖于抽象(稳定)。

例如:

class A 依赖 class B ,此时的 class A 为高层模块,class B 为低层模块。如果要进行修改使 class A 依赖 class C , 那么必须要修改 class A 的源码。此时,就发生了高层模块依赖低层模块。如果使用一个公共的接口 interface D 抽象 class Bclass C , 那么 class A 就可以依赖 interface D ,高层模块不依赖于低层模块。如果使 class A 也抽象一个抽象接口 interface IA,那么,只需要了解 interface IAinterface D 之间的关系即可,无需关心实现细节。此刻,便完成了高层模块和低层模块都依赖于接口,同时也完成了抽象不依赖于实现细节,实现细节依赖于抽象

我们采用抽象接口定义好规则规范,而不需要关系具体实现,提高了设计的稳定性。

我们定义了两个类,一个为 Movie 另一个为 Television,通过 Television.play() 方法进行内容播放。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Movie { fun show() { println("这是电影") } } class Television { fun play(movie: Movie) { movie.show() } } fun main() { val television = Television() val movie = Movie() television.play(movie) // 这是电影 }

目前来看没有问题,那么如果现在电视剧要播放动画呢?我们需要重新建立一个类 Cartoon,并且修改 play() 方法 和 main 函数。

此刻说明在设计上有问题,我们的高层模块(Television)依赖底层模块(Movie)。

如果先将 MovieCartoon 进行抽象,使 Television 不去依赖具体实现,而去依赖接口。

经过修改后,Television不在依赖任何一个具体的类,而是依赖他们的抽象接口,以后无论增加播放什么,例如添加一个广告 Ad.class 只需要添加新的类,并且实现 ITVContent 接口,就可以完成新的播放内容的更换。

如果要更换播放平台呢?不在电视上播放,而在电影院进行播放。

我们只需要添加一个 IPlayer 的接口,并且有未实现的 paly 方法。让 TelevisionCinema 去实现即可。

经过简单的修改,无论是 Television 还是 Cinema 都不在依赖具体的类,而是依赖抽象的接口,以后无论扩展什么播放方法和播放内容,都不需要对之前的类进行修改。同时也不存在抽象的依赖具体实现,而是具体实现全部依赖于抽象。完成了解耦问题,将变换进行了隔离。

开闭原则 (OCP)

对扩展开发,对修改封闭,类模块应该是可以扩展的,但是不可以修改。

什么叫做修改,什么叫做扩展?修改是指对已有的源代码进行修改,而扩展是对当前没有的类或者方法进行添加。

对于上述示例,第一次代码还没有进行修改的时候,代码就进行了修改,每次修改必须对源码进行修改来实现新的功能。最终的代码版本,进行新功能的添加只需要扩展新的类即可,无需对已有的代码进行修改。这样便实现了开闭原则。

单一职责原则(SRP)

不要存在多于一个导致类变更的原因,一个类只负责一项原则。每个类负责的职责不同,进行修改的时候不会对其他类造成影响或者改变。

里氏 Liskov 替换原则(LSP)

子类必须能够替换它们的基类,继承表达类型抽象。LSP 是继承复用的基石,只有子类可以替换父类,并且之前功能不受到影响时,父类才能真正的被复用。是对开闭原则的补充。

接口隔离原则(ISP)

类之间的依赖关系应该建立在最小的接口上。建立单一的接口,不要建立庞大臃肿的接口,接口中的方法尽量少,而不是去建立一个庞大的接口供依赖去使用。

其他原则

优先使用对象组合,而不是继承

继承表达的一种类属关系,例如 大熊猫继承动物,动物继承于生物,这是表达了一种类属关系(is-a)。

继承在某种程度上破坏了封装性,子类父类耦合度较高。

例如子类无法继承多个父类,父类中的方法子类无条件拥有,从父类继承的方法不能在运行时进行改变。这些都时继承所带来的缺点或者不足。

而对象组合只要求被组合的对象具有良好的定义接口。

针对接口编程,而不是针对实现编程

不要将变量类型声明为具体某个类型,而是声明为接口;客服端无需知道对象的具体类型,只需要知道对象的接口;减少系统中各部分的依赖关系,从而实现“高内聚,低耦合”的设计。

接口标准化是软件开发的重要举措,面向接口设计可以使工程分工,代码解耦。


不同的设计模型对设计原则有着不同的依赖,设计原则指导的设计模式的进行。

相关文章
|
8月前
|
测试技术 监控 程序员
软件体系结构 - 净室软件工程
软件体系结构 - 净室软件工程
172 1
|
8月前
|
敏捷开发 开发框架 测试技术
软件体系结构 - 软件工程(1)
【4月更文挑战第1天】软件体系结构 - 软件工程(1)
103 0
|
8月前
|
设计模式 缓存
理解并应用设计模式在软件开发中的重要性
【5月更文挑战第20天】设计模式是软件开发中的最佳实践,用于解决常见设计问题,提高代码可读性、可维护性、可扩展性和灵活性。本文介绍了为何需要设计模式(如管理依赖、增强可重用性、设计易扩展系统)以及常见的设计模式:工厂模式(封装对象创建)、单例模式(确保类唯一实例)、观察者模式(事件驱动)和适配器模式(解决接口不兼容)。应用设计模式的关键步骤包括识别问题、选择模式、实现模式及测试优化。设计模式对于提升代码质量和降低系统风险至关重要。
|
8月前
|
项目管理
软件体系结构 - 软件工程(2)
【4月更文挑战第2天】软件体系结构 - 软件工程(2)
45 0
|
8月前
|
存储 关系型数据库 uml
00003.七大软件架构设计原则
00003.七大软件架构设计原则
85 0
|
存储 人工智能
软件工程——面向对象技术
软件工程——面向对象技术
224 0
软件工程——面向对象技术
|
数据库
软件设计原则
软件设计原则
|
设计模式 数据库
面向对象的七大设计原则
面向对象的七大设计原则
300 0
|
算法
【软件工程】——软件设计
【软件工程】——软件设计
129 0
【软件工程】——软件设计
|
设计模式 存储 关系型数据库
浅析软件工程中的一些常见设计原则(上)
老子说:有道无术,术尚可求也。有术无道,止于术。如果说设计模式是“术”,那么设计原则就是“道”。今天,我们一起来聊聊软件工程中一些常用的设计原则。

相关课程

更多