0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

SOLID設(shè)計(jì)原則

汽車電子技術(shù) ? 來(lái)源:typedef ? 作者: typedef ? 2023-02-21 10:10 ? 次閱讀

前序

C語(yǔ)言開(kāi)發(fā)的應(yīng)該都知道,C是面向過(guò)程開(kāi)發(fā)的,而c++是面向?qū)ο箝_(kāi)發(fā)的。而封裝、繼承與多態(tài)是面向?qū)ο箝_(kāi)發(fā)的三大特征。

但你可能不知道OOD(Object-Oriented Design)還有五大基本原則,被Bob大叔稱為SOLID原則,字母為每個(gè)原則的首字母,遵循這些原則能夠讓你的代碼在擴(kuò)展性、維護(hù)性以及重用性提高。而這些不正是我們所追求的嗎?

接下來(lái)我們就一塊學(xué)習(xí)學(xué)習(xí)這些原則,內(nèi)容較多,建議先收藏后反復(fù)觀看,文章末尾有很多參考鏈接。

五大基本原則-SOLID

1. SRP

SRP(The Single Responsibility Principle)單一職責(zé)原則。

SRP是SOLID五大設(shè)計(jì)原則中最容易被誤解的一個(gè),SRP不就是每個(gè)模塊都應(yīng)該只做一件事嗎?非也非也,這只是在實(shí)現(xiàn)底層細(xì)節(jié)的實(shí)際原則,并非是SRP的全部。

SRP最初是這樣描述的:

任何一個(gè)模塊都應(yīng)該有且只有一個(gè)被修改的原因(There should never be more than one reason for a class to change)

SRP的定義幾經(jīng)迭代,最終被Robert C.Martin在《Clean Architecture》中定義為:

任何一個(gè)軟件模塊都應(yīng)該只對(duì)某一類行為者負(fù)責(zé)

那么上文中提到的軟件模塊究竟是指什么呢?大部分情況下,其最簡(jiǎn)單的定義就是指一個(gè)源代碼文件。然而有些編程語(yǔ)言和編程環(huán)境并不是用源代碼文件來(lái)存儲(chǔ)程序的。在這些情況下,軟件模塊指的就是一組緊密相關(guān)的函數(shù)和數(shù)據(jù)結(jié)構(gòu)。

來(lái)看一個(gè)正面例子,C標(biāo)準(zhǔn)庫(kù)中的模塊就是用來(lái)處理數(shù)學(xué)相關(guān)的,模塊就是用來(lái)處理字符串相關(guān)的的,等等...,每個(gè)模塊職責(zé)都比較明確。

再來(lái)看一個(gè)反面例子,還記得剛開(kāi)始學(xué)習(xí)單片機(jī)編程的時(shí)候,項(xiàng)目工程中從始至終就一個(gè)main源文件,真的是連頭文件都不寫(xiě)的,一個(gè)main里面包含了LED、按鍵等相關(guān)全部代碼,這明顯是不符合SRP這一原則的。就像下圖一樣。

圖片

2. OCP

OCP(The Open-Closed Principle)開(kāi)放封閉原則。

OCP的定義如下:

軟件實(shí)體應(yīng)當(dāng)對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉(Software entities should be open for extension,but closed for modification)

設(shè)計(jì)良好的計(jì)算機(jī)軟件應(yīng)該易于擴(kuò)展,同時(shí)抗拒修改。換句話說(shuō),一個(gè)良好的計(jì)算機(jī)系統(tǒng)應(yīng)該在不需要修改的前提下就可以輕易被擴(kuò)展。

OCP是系統(tǒng)框架設(shè)計(jì)的主導(dǎo)原則,其主要目的是讓系統(tǒng)易于擴(kuò)展,同時(shí)限制其每次被修改所影響的范圍。實(shí)現(xiàn)的方式是通過(guò)將系統(tǒng)劃分為一系列的組件,并且將這些組件的依賴關(guān)系按層次結(jié)構(gòu)進(jìn)行組織,使得高階的組件不會(huì)因低階組件被修改而受到影響。

我們來(lái)看一個(gè)網(wǎng)絡(luò)中協(xié)議的例子,如下圖:圖片

圖中分為三個(gè)層級(jí),最上方層級(jí)最高,每個(gè)層級(jí)有若干組件,高層級(jí)的組件依賴低層級(jí)的組件。## 3. LSP

LSP(LSP-Liskov Substitution Principle)里氏替換原則。

LSP定義:

使用基類對(duì)象指針或引用的函數(shù)必須能夠在不了解衍生類的條件下使用衍生類的對(duì)象(Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it)

里氏代換原則中說(shuō),任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn)。只有當(dāng)衍生類可以替換掉基類,軟件單位的功能不受到影響時(shí),基類才能真正被復(fù)用,而衍生類也能夠在基類的基礎(chǔ)上增加新的行為。

我們來(lái)看一個(gè)經(jīng)典的反面案例,正方形(Square)與長(zhǎng)方形(Rectangle)。

那這里提出疑問(wèn)了,正方形和長(zhǎng)方形之間的繼承關(guān)系是如何呢?

如果A is-a B,則認(rèn)為B是基類,A為子類,A應(yīng)該繼承B。那這個(gè)簡(jiǎn)單了,眾所周知正方形是長(zhǎng)方形,立即推,長(zhǎng)方形是基類,正方形是子類,正方形應(yīng)該繼承長(zhǎng)方形。

圖片

基類長(zhǎng)方形中有SetHeight()和SetWidth()方法,但是子類正方形有一個(gè)特點(diǎn),長(zhǎng)和寬是相等的,所以在實(shí)現(xiàn)SetHeight()和SetWidth()都必須同時(shí)設(shè)置寬和高,我們來(lái)看代碼。

圖片

還是那句話任何基類可以出現(xiàn)的地方,子類一定可以出現(xiàn),所以在創(chuàng)建Rectangle對(duì)象指針的時(shí)候,這里其實(shí)給的是子類的對(duì)象,最終代碼運(yùn)行斷言報(bào)錯(cuò)。

Assertion failed: rect->GetArea() == 10, file .\\main.cpp, line 10

如果new出來(lái)的對(duì)象是Rectangle,則程序能夠正常執(zhí)行。如果new出來(lái)的是Square則會(huì)進(jìn)入斷言。從而Square不能代替Rectangle,所以不符合LSP原則,實(shí)際上Square并不是Rectangle的子類。

正方形是長(zhǎng)方形,但是他們的行為并不一樣,所謂的行為,就是抽象出來(lái)的東西。正方形只要有一個(gè)設(shè)置邊長(zhǎng)的方法就行了,而長(zhǎng)方形需要設(shè)置寬和高兩種方法。

4. ISP

ISP(ISP-Interface Segregation Principle)接口隔離原則。

ISP定義:

不應(yīng)強(qiáng)制客戶端依賴于它們不使用的接口(Clients should not be forced to depend upon interfaces that they do not use.)

該原則還有另外一個(gè)定義:一個(gè)類對(duì)另一個(gè)類的依賴應(yīng)該建立在最小的接口上(The dependency of one class to another one should depend on the smallest possible interface)

假如現(xiàn)在有一個(gè)OPS類。用戶1只需要使用OPS類的op1方法,用戶2只需要OPS類的op2方法,但是呢,OPS類除了提供op1和op2方法還提供了若干方法。如下圖:

圖片

此時(shí)用戶2沒(méi)什么意見(jiàn),心想著反正能實(shí)現(xiàn)我要的功能就可以了。

但是呢,用戶1不愿意,于是就去找開(kāi)發(fā)人員理論,我就要實(shí)現(xiàn)一個(gè)op1功能,給我整這么多依賴干啥。除了這個(gè)功能,其他的全部都給我隱藏掉,下班之前我就要,說(shuō)完頭一扭就走了。

開(kāi)發(fā)人員心想,這么簡(jiǎn)單的事情,讓我下班之前給你,這不是圖片眼看人低嗎,說(shuō)完就在用戶1和OPS之間又封裝一層IU1Ops接口,兩分鐘搞定。于是就去跟用戶1說(shuō),你用IU1Ops,里面有你要的接口,拿去用吧。說(shuō)完頭一扭就走了。模型如下圖:

圖片

接口隔離原則和單一職責(zé)都是為了提高類的內(nèi)聚性、降低它們之間的耦合性,體現(xiàn)了封裝的思想,但兩者是不同的:

  • 單一職責(zé)原則注重的是職責(zé),而接口隔離原則注重的是對(duì)接口依賴的隔離。
  • 單一職責(zé)原則主要是約束類,它針對(duì)的是程序中的實(shí)現(xiàn)和細(xì)節(jié);接口隔離原則主要約束接口,主要針對(duì)抽象和程序整體框架的構(gòu)建。

5. DIP

DIP(DIP-Dependency Inversion Principle)依賴倒置原則。

DIP定義:

高層次的模塊不應(yīng)該依賴低層次的模塊,他們都應(yīng)該依賴于抽象(High level modules should not depend upon low level modules. Both should depend upon abstractions)

抽象不應(yīng)該依賴于具體實(shí)現(xiàn),具體實(shí)現(xiàn)應(yīng)該依賴于抽象(Abstractions should not depend upon details. Details should depend upon abstractions)

這個(gè)名字看著有點(diǎn)別扭,“依賴”還“倒置”,這到底是啥意思?

依賴指兩個(gè)相對(duì)獨(dú)立的對(duì)象,當(dāng)一個(gè)對(duì)象負(fù)責(zé)構(gòu)造另一個(gè)對(duì)象的實(shí)例,或者依賴另一個(gè)對(duì)象的服務(wù)時(shí),這兩個(gè)對(duì)象之間主要體現(xiàn)為依賴關(guān)系。

老樣子,看示例,現(xiàn)在甲方需要能讓BMW車跑起來(lái)的功能,再看一下乙方的設(shè)計(jì)。

圖片

司機(jī)有駕駛BMW車輛的方法,BMW車輛有run的方法,所以是甲方滿足需求的。

后來(lái)甲方需求變了,甲方不僅要能開(kāi)BMW車,也要能開(kāi)Benz車,卻發(fā)現(xiàn)使用乙方原來(lái)的的設(shè)計(jì)Benz車卻開(kāi)不起來(lái),因?yàn)?driver()只接受BMW的車輛,不接受Benz的車輛,這明顯不合理,一個(gè)司機(jī)會(huì)開(kāi)BMW卻不會(huì)開(kāi)Benz,太反常了。于是去找乙方重新設(shè)計(jì)。

乙方也認(rèn)識(shí)到了不足,經(jīng)過(guò)多方討論終于有了如下設(shè)計(jì)。

圖片

對(duì)于每種車輛,都應(yīng)該有一個(gè)run的方法,所有的車輛都應(yīng)該繼承ICar實(shí)現(xiàn)。而司機(jī)呢,也不應(yīng)該依賴具體的車輛,而應(yīng)該依賴所有車輛的抽象方法。原本直接指向BMW的依賴箭頭被反置了?,F(xiàn)在即使甲方在添加別的車輛,司機(jī)仍然能開(kāi)。不會(huì)出現(xiàn)只會(huì)開(kāi)BMW而不會(huì)開(kāi)其他車輛的情況了。

簡(jiǎn)單來(lái)說(shuō),依賴倒轉(zhuǎn)原則就是指:代碼要依賴于抽象的類,而不要依賴于具體的類;要針對(duì)接口或抽象類編程,而不是針對(duì)具體類編程。根據(jù)上面的例子可以加深理解。

依賴倒置原則(Dependency Inversion Principle)是很多面向?qū)ο蠹夹g(shù)的根基。它特別適合應(yīng)用于構(gòu)建可復(fù)用的軟件框架,并且,因?yàn)槌橄蠛图?xì)節(jié)已經(jīng)彼此隔離,代碼也變得更易維護(hù)。

采用依賴倒置原則可以減少類間的耦合性,提高系統(tǒng)的穩(wěn)定性,減少并行開(kāi)發(fā)引起的風(fēng)險(xiǎn),提高代碼的可讀性和可維護(hù)性。

參考鏈接

  • https://www.freecodecamp.org/news/solid-principles-explained-in-plain-english/
  • https://www.cnblogs.com/gaochundong/p/liskov_substitution_principle.html
  • https://davesquared.net/2009/01/introduction-to-solid-principles-of-oo.html
  • http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod
  • https://www.jianshu.com/p/3875283e26c7
  • https://www.jianshu.com/p/c3ce6762257c
  • https://zhuanlan.zhihu.com/p/280765580
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7594

    瀏覽量

    135861
  • C++
    C++
    +關(guān)注

    關(guān)注

    21

    文章

    2100

    瀏覽量

    73453
  • Solid
    +關(guān)注

    關(guān)注

    0

    文章

    8

    瀏覽量

    8979
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    為了學(xué)習(xí)內(nèi)核開(kāi)發(fā),大佬手搓了一個(gè)輕量級(jí)操作系統(tǒng)YiYiYa OS

    YiYiYa操作系統(tǒng)是一個(gè)樸實(shí)無(wú)華的操作系統(tǒng),追求快速開(kāi)發(fā),最小實(shí)現(xiàn),同時(shí)遵循SOLID原則。編碼簡(jiǎn)潔明了,非常適合學(xué)習(xí)操作系統(tǒng)的同學(xué)。目前既有宏內(nèi)核,也逐步實(shí)現(xiàn)了微內(nèi)核架構(gòu),未來(lái)將會(huì)是混合內(nèi)核
    發(fā)表于 08-27 10:08

    為了學(xué)習(xí)內(nèi)核開(kāi)發(fā),大佬手搓了一個(gè)輕量級(jí)操作系統(tǒng)YiYiYa OS

    作者:evilbinary(鴨佬) YiYiYa操作系統(tǒng)是一個(gè)樸實(shí)無(wú)華的操作系統(tǒng),追求快速開(kāi)發(fā),最小實(shí)現(xiàn),同時(shí)遵循SOLID原則。編碼簡(jiǎn)潔明了,非常適合學(xué)習(xí)操作系統(tǒng)的同學(xué)。目前既有 宏內(nèi)核 ,也
    發(fā)表于 08-30 14:57

    AD 鋪銅之 Solid 和 Hatched 區(qū)別

    想自己做一個(gè)MSP430的開(kāi)發(fā)板,在對(duì)地鋪銅的時(shí)候選項(xiàng)里 Solid 和 Hatched 兩種,到底有什么區(qū)別呢?不知道啊不知道~~就高手教教
    發(fā)表于 04-28 10:28

    AD 如何挖空Solid Region

    我用的AD17,用place-solid Region花了一大塊銅皮連接電源網(wǎng)絡(luò),直接覆蓋了幾個(gè)電容的焊盤,現(xiàn)在想把這些電容的焊盤做成熱焊盤的樣子,要不然焊接的時(shí)候散熱太快,但是沒(méi)有辦法用keep out和pour cutout來(lái)做挖空區(qū)域。請(qǐng)教下熟練的兄弟有什么辦法嗎?
    發(fā)表于 07-24 17:33

    SOLID設(shè)計(jì)原則

    設(shè)計(jì)原則SOLID)使用各個(gè)原則的首字母組成了一個(gè)單詞:SOLID。SRP:Single Responsibility Principle,單一職責(zé)
    發(fā)表于 11-08 07:44

    Microwave Solid State Circuit

    Microwave Solid State Circuit Design * Provides detailed coverage of passive and active RF
    發(fā)表于 12-23 22:49 ?15次下載

    Solid State Relay固態(tài)繼電器

    Solid State Relay固態(tài)繼電器
    發(fā)表于 11-30 11:59 ?30次下載

    基于Solid Edge的飛機(jī)雷達(dá)熱交換機(jī)設(shè)計(jì)

    介紹了雷達(dá)熱交換機(jī)的機(jī)械設(shè)計(jì)方案,闡述了Solid Edge的功用以及采用Solid Edge設(shè)計(jì)雷達(dá)熱交換機(jī)機(jī)械零部件機(jī)構(gòu)的過(guò)程,以及利用裝配環(huán)境進(jìn)行零部件裝配和二維工程圖設(shè)計(jì)環(huán)境進(jìn)行二
    發(fā)表于 02-22 12:13 ?20次下載

    Solid Edge運(yùn)動(dòng)仿真教程

    Solid Edge運(yùn)動(dòng)仿真教程 運(yùn)動(dòng)仿真(Motion)是Solid Edge裝配環(huán)境內(nèi)一個(gè)獨(dú)立的功能,單擊裝配主菜單“環(huán)境”中的“運(yùn)動(dòng)仿真”命令,便可進(jìn)入“運(yùn)動(dòng)仿真”環(huán)境。
    發(fā)表于 04-29 14:21 ?100次下載

    固態(tài)功率控制器電路,Solid State Power Co

    Solid State Power Controller
    發(fā)表于 02-27 09:45 ?1484次閱讀
    固態(tài)功率控制器電路,<b class='flag-5'>Solid</b> State Power Co

    固態(tài)繼電器開(kāi)關(guān)電路,Solid state relay sw

    固態(tài)繼電器開(kāi)關(guān)電路,Solid state relay switch Description&nbs
    發(fā)表于 03-28 22:15 ?2255次閱讀
    固態(tài)繼電器開(kāi)關(guān)電路,<b class='flag-5'>Solid</b> state relay sw

    solid work 安裝步驟資料分享

    solid work 安裝步驟
    發(fā)表于 04-11 09:57 ?4次下載

    做軟件工程師必須要知道的20個(gè)問(wèn)題

    針對(duì)面向?qū)ο蟮脑O(shè)計(jì)與分析:為了讓軟件有更好的可維護(hù)性,重用性以及快速開(kāi)發(fā), 簡(jiǎn)短的OOAD與它的SOLID原則對(duì)于每一個(gè)軟件工程師來(lái)說(shuō)都是該牢記的。
    的頭像 發(fā)表于 10-17 10:38 ?3508次閱讀

    Solid Sands任命中國(guó)核心經(jīng)銷商

    編譯器和庫(kù)測(cè)試及認(rèn)證技術(shù)的全球領(lǐng)導(dǎo)者 Solid Sands 宣布在中國(guó)任命新的戰(zhàn)略供應(yīng)商。
    的頭像 發(fā)表于 09-17 14:42 ?1441次閱讀
    <b class='flag-5'>Solid</b> Sands任命中國(guó)核心經(jīng)銷商

    《嵌入式軟件設(shè)計(jì)方法》--設(shè)計(jì)原則

    設(shè)計(jì)原則SOLID)使用各個(gè)原則的首字母組成了一個(gè)單詞:SOLID。SRP:Single Responsibility Principle,單一職責(zé)
    發(fā)表于 11-03 15:36 ?12次下載
    《嵌入式軟件設(shè)計(jì)方法》--設(shè)計(jì)<b class='flag-5'>原則</b>