iOS基本功

六大设计原则(SOLID)[转]

2020-06-18  本文已影响0人  SnoopPanda
六大设计原则(SOLID)
SOLID

把这六个原则的首字母联合起来(两个 L 算做一个)就是 SOLID (solid,稳定的),其代表的含义就是这六个原则结合使用的好处:建立稳定、灵活、健壮的设计。

一、单一职责原则

一个类应该只有一个发生变化的原因

There should never be more than one reason for a class to change.

一个类只负责一个职责,每个类只需要负责自己的那部分,类的复杂度就会降低。如果职责互粉得很清楚,那么代码维护起来也更加容易。试想如果所有的功能都放在了一个类中,那么这个类就会变得非常臃肿,而且一旦发现bug,要在所有代码中去寻找;更改某个地方,可能要改变整个代码的结构,想想都非常可怕。当然一般时候,没有人会去这么写。

这个原则不仅仅适用于类,对于接口和方法也适用,即一个接口/方法,只负责一件事,这样的话,接口就会变得简单,方法中的代码也会更少,易读,便于维护。

事实上,由于一些其他的因素影响,类的单一职责在项目中是很难保证的。通常,接口和方法的单一职责更容易实现。

单一职责原则的好处:

二、开闭原则

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

Software entities like classes, modules and functions should be open for extension but closed for modification

在软件的生命周期内,因为变化、升级和维护等原因需要对软件原有代码进行修改,可能会给旧代码引入错误,也有可能会使我们不得不对整个功能进行重构,并且需要原有代码经过重新测试。这是引入开闭原则的原因,用抽象构建构架,用实现扩展细节,因为抽象灵活性好,适应性广,只要抽象的合理,可以基本保证架构的稳定。而软件中易变的细节,我们用从抽象派生的实现类来进行扩展,当软件需要发生变化时,我们只需要根据需求重新派生一个实现类来扩展就可以了,当然前提是抽象要合理,要对需求的变更有前瞻性和预见性。

三、里氏替换原则定义

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

Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.

里氏替换原则的意思是,所有基类在的地方,都可以换成子类,程序还可以正常运行。这个原则是与面向对象语言的继承特性密切相关的。

继承的优点:

继承的缺点:

里氏替换原则对继承进行了规则上的约束

里氏替换原则对继承进行了规则上的约束,这种约束主要体现在四个方面:

四、迪米特法则

只与你的直接朋友交谈,不跟“陌生人”说话

Talk only to your immediate friends and not to strangers
如果两个软件实体无须直接通信,那么就不应当发生直接的互相调用,可以通过第三方转发该调用。其目的是降低类之间的耦合度,提高模块的相对独立性。

注意事项:过度使用迪米特法则会使系统产生大量的中介类,从而增加系统的复杂性,使模块之间的通信效率降低。所以,在采用迪米特法则时需要反复权衡,确保高内聚和低耦合,保证系统的结构清晰。

迪米特法则的实现方法:

例子:一个中介,客户只要找中介要满足的楼盘,而不必跟每个楼盘发生联系。

五、接口隔离原则

1、客户端不应该依赖它不需要的接口
2、类间的依赖关系应该建立在最小的接口上

Clients should not be forced to depend upon interfaces that they don`t use.
The dependency of one class to another one should depend on the smallest possible.
要为各个类建立它们需要的专用接口,而不要试图去建立一个很庞大的接口供所有依赖它的类去调用。

接口隔离原则和单一职责的区别
接口隔离原则和单一职责都是为了提高类的内聚性、降低它们之间的耦合性,体现了封装的思想,但两者不同的:

接口隔离原则的优点
接口隔离原则是为了约束接口、降低类对接口的依赖性,遵循接口隔离原则有一下5个优点:

接口隔离原则的实现方法

六、依赖倒置原则

1、上层模块不应该依赖底层模块,它们都应该依赖于抽象
2、抽象不应该依赖于细节,细节应该依赖于抽象

High level modules should not depend upon low level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.

举个例子,现在你需要实现一个比萨店,你第一件想到的事情是什么?我想到的是一个比萨店,里面有很多具体的比萨,如:芝士比萨、素食比萨、海鲜比萨……
比萨店是上层模块,比萨是下层模块,如果把比萨店和它依赖的对象画成一张图,看起来是这样:


image.png

没错!先从顶端开始,然后往下到具体类,但是,正如你看到的你不想让比萨店理会这些具体类,要不然比萨店将全都依赖这些具体类。现在“倒置”你的想法……别从上层模块比萨店开始思考,而是从下层模块比萨开始,然后想想看能抽象化些什么。你可能会想到,芝士比萨、素食比萨、海鲜比萨都是比萨,所以它们应该共享一个Pizza接口。对了,你想要抽象化一个Pizza。好,现在回头重新思考如何设计比萨店。

image.png

此例子也很好的解释了“上层模块不应该依赖底层模块,它们都应该依赖于抽象。”,在最开始的设计中,高层模块PizzaStroe直接依赖低层模块(各种具体的Pizaa),调整设计后,高层模块和低层模块都依赖于抽象(Pizza)

参考:
https://www.cnblogs.com/LangZXG/p/6242927.html
https://www.jianshu.com/p/3268264ae581

上一篇 下一篇

猜你喜欢

热点阅读