软件工程设计原则
依赖倒置原则 (DIP)
高层模块(稳定)不应该依赖于低层模块(变化),二者都应该依赖于抽象(稳定)。
抽象(稳定)不应该依赖于实现细节(变化),实现细节(变化)应该依赖于抽象(稳定)。
例如:
class A
依赖 class B
,此时的 class A
为高层模块,class B
为低层模块。如果要进行修改使 class A
依赖 class C
, 那么必须要修改 class A
的源码。此时,就发生了高层模块依赖低层模块。如果使用一个公共的接口 interface D
抽象 class B
和 class C
, 那么 class A
就可以依赖 interface D
,高层模块不依赖于低层模块。如果使 class A
也抽象一个抽象接口 interface IA
,那么,只需要了解 interface IA
和 interface 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
)。
如果先将 Movie
和 Cartoon
进行抽象,使 Television
不去依赖具体实现,而去依赖接口。
经过修改后,Television
不在依赖任何一个具体的类,而是依赖他们的抽象接口,以后无论增加播放什么,例如添加一个广告 Ad.class
只需要添加新的类,并且实现 ITVContent
接口,就可以完成新的播放内容的更换。
如果要更换播放平台呢?不在电视上播放,而在电影院进行播放。
我们只需要添加一个 IPlayer
的接口,并且有未实现的 paly
方法。让 Television
和 Cinema
去实现即可。
经过简单的修改,无论是 Television
还是 Cinema
都不在依赖具体的类,而是依赖抽象的接口,以后无论扩展什么播放方法和播放内容,都不需要对之前的类进行修改。同时也不存在抽象的依赖具体实现,而是具体实现全部依赖于抽象。完成了解耦问题,将变换进行了隔离。
开闭原则 (OCP)
对扩展开发,对修改封闭,类模块应该是可以扩展的,但是不可以修改。
什么叫做修改,什么叫做扩展?修改是指对已有的源代码进行修改,而扩展是对当前没有的类或者方法进行添加。
对于上述示例,第一次代码还没有进行修改的时候,代码就进行了修改,每次修改必须对源码进行修改来实现新的功能。最终的代码版本,进行新功能的添加只需要扩展新的类即可,无需对已有的代码进行修改。这样便实现了开闭原则。
单一职责原则(SRP)
不要存在多于一个导致类变更的原因,一个类只负责一项原则。每个类负责的职责不同,进行修改的时候不会对其他类造成影响或者改变。
里氏 Liskov 替换原则(LSP)
子类必须能够替换它们的基类,继承表达类型抽象。LSP 是继承复用的基石,只有子类可以替换父类,并且之前功能不受到影响时,父类才能真正的被复用。是对开闭原则的补充。
接口隔离原则(ISP)
类之间的依赖关系应该建立在最小的接口上。建立单一的接口,不要建立庞大臃肿的接口,接口中的方法尽量少,而不是去建立一个庞大的接口供依赖去使用。
其他原则
优先使用对象组合,而不是继承
继承表达的一种类属关系,例如 大熊猫继承动物,动物继承于生物,这是表达了一种类属关系(is-a)。
继承在某种程度上破坏了封装性,子类父类耦合度较高。
例如子类无法继承多个父类,父类中的方法子类无条件拥有,从父类继承的方法不能在运行时进行改变。这些都时继承所带来的缺点或者不足。
而对象组合只要求被组合的对象具有良好的定义接口。
针对接口编程,而不是针对实现编程
不要将变量类型声明为具体某个类型,而是声明为接口;客服端无需知道对象的具体类型,只需要知道对象的接口;减少系统中各部分的依赖关系,从而实现“高内聚,低耦合”的设计。
接口标准化是软件开发的重要举措,面向接口设计可以使工程分工,代码解耦。
不同的设计模型对设计原则有着不同的依赖,设计原则指导的设计模式的进行。
- 点赞
- 收藏
- 关注作者
评论(0)