Python面向對象—六大設計原則


設計原則

-閉原則(目標、總的指導思想)

Open Closed Principle

“開”指的是允許一個類甚至往大了說允許一個系統隨時可以對自己的功能進行擴展。

“閉”指的是不允許在擴展和修改功能的時候觸及到已經寫好的底層代碼(比如父類)。

舉一個比較淺顯的例子,可以理解為電腦與硬盤以及 U 盤的關系。

面向過程類型的編寫會把所有關鍵代碼寫在一起,就好比在給一個已經裝好的主機箱添加硬盤,那首先需要先拆開主機箱,然后將裝機時為了美觀扎好的數據線進行拆解,選擇數據線插在硬盤上,再把剩下的線重新扎好,重新封裝好主機箱,費時費力。

而如果想給已經裝好的主機箱加一個U盤,只需要將准備好的U盤對准USB接口接入,就可以了,在整個過程中主機箱早就裝好的內部構造並沒有任何變化;而如果想對 U 盤進行擴容或者修改,那么只需要操作 U 盤甚至是替換 U 盤,過程中主機箱是不會發生任何改變的。相比之下,效率就更高了。

那么把這個原理套用在代碼之中,盡可能將后期會變化的因素放在外部,而將確定不會產生改變的固定因素作為底層,這樣在后期代碼擴展和修改中效率就會比較理想。同時,這種將代碼互相拆分,來避免在修改過程中牽一發而動全身的特點,稱之為封裝。

對擴展開放,對修改關閉。

增加新功能,不改變原有代碼。

類的單一職責(一個類的定義)

Single Responsibility Principle   

所謂的單一指的應該是一個類能被修改的原因只能有一個,單一原則直接針對的問題是代碼的耦合性,而所謂的耦合性指的就是在面臨修改的時候被波及的范圍,那么假設一個類里存在兩個或者三個功能,但是每次整個類只會因為同一件事情去發生修改,發生其他問題都不會觸及到此類,那么耦合性就已然降至理想狀態了,除此之外的分類細化縱然沒有影響代碼后期的工作難度,但也是在消耗生成代碼時的時間精力。

一個類有且只有一個改變它的原因。

依賴倒置(依賴抽象)

Dependency Inversion Principle

依賴關系,在面向對象思想過程中首先要做的是分,將需要改變的代碼分離出去,將不需要改變的代碼整合到一起,至此,我們實現了最基本的兩個封裝,之后,整合的代碼往往需要調取會產生改變的代碼,這種關系可以理解為最直接的依賴關系.

而當產生變化時,這種基礎依賴關系就會隨之產生變化,變化的越多,依賴關系修改的越多。

為了避免后期代碼的變化導致工程量的增加,首先要做的是將會變化的代碼變成一個大的框架,給它們一個統一的類型,也就是統一繼承,給一個父類,父類本身只是作為一個中轉站用來銜接固定代碼區域和變化代碼區域,換句話說,此時固定代碼區域如果想要調用變化代碼區域,必須要經過父類,通過把傳統的依賴具象代碼關系轉變成依賴抽象代碼方式,就稱之為依賴倒置。

以下是對這個代碼結構進行舉例演示,比如“張三駕駛汽車”這件事,“張三”這個人以及“駕駛”這件事在當前的架構里是不會發生改變的,所以統一封裝在固定代碼區域,而駕駛的“汽車”作為可能發生變化的代碼封裝在變化代碼區域,隨后所有汽車類再統一繼承給一個叫做“載具”的父類,這個類因為沒有具體的特征所以是抽象的,而張三每次駕駛不同載具都要先指向“載具”,再由“載具”按需求去挑選繼承了自己的每一個具體的汽車子類,如果有新的需求,還可以再繼續擴展子類。

如果一開始“張三”作為人也是可以替換的,或者“駕駛”這件事也是可以替換的,那么同樣將“張三”封裝到一個變化區域,繼承給一個叫做“人”的父類;“駕駛”這件事也可以繼承給類似於“行為”這樣的抽象父類,既滿足依賴倒置原則。

客戶端代碼(調用的類)盡量依賴(使用)抽象的組件。

抽象的是穩定的。實現是多變的。

組合復用原則(復用的最佳實踐)

Composite Reuse Principle

組合復用原則原意指的是在組合關系和繼承關系都能滿足業務要求時優先使用組合關系。不過根據整體思想來說,我個人的觀點是應該將組合復用理解為既是指在泛化、關聯、依賴(詳見類與類的關系)能滿足要求的情況下,盡量使用其中耦合度最低的關系。盡管相比之下繼承關系耦合度並不比其他兩種關系好,但是不代表繼承關系一文不值,在很多情況下,繼承的實用性依然不錯。

如果僅僅為了代碼復用優先選擇組合復用,而非繼承復用。

組合的耦合性相對繼承低。

里氏替換(繼承后的重寫,指導繼承的設計)

Liskov Substitution Principle

里氏替換針對的依然是繼承關系,只要是父類能參與的任何構造,子類完全可以勝任,所以里氏替換的主要思想就是只要父類可以被調用,子類就一定要代替父類被調用。這種情況並不是說父類沒有意義,相反的,里氏替換進一步要求父類盡可能不要存在太具體的功能,能抽象就盡量抽象任何的修改都完全依靠子類來補充和修改,從而進一步實現開閉原則(父類對修改關閉,子類對修改開放)。

同時補充一下,因為每一個子類在父類的構造上都可以額外拓展,於是,就算每一個子類內部的方法名字跟父類完全一樣,但是因為每個子類都對這同一個方法產生了新的拓展,所以在調用這個方法的時候,方法名始終沒有任何改變,但是方法本身卻是隨着子類的不同而千變萬化的。這種現象就稱之為多態。所以里氏替換原則也是在為父類的抽象化和子類的多態化進行闡述。

父類出現的地方可以被子類替換,在替換后依然保持原功能。

子類要擁有父類的所有功能。

子類在重寫父類方法時,盡量選擇擴展重寫,防止改變了功能。

迪米特法則(類與類交互的原則)

Law of Demeter

迪米特法則也被戲稱為“最少知道法則”,其實說白了就是針對面向對象里的低耦合。它的本意指的是類與類之間盡可能不要有太多的關聯,當一個類需要產生變化時,其他的類盡量做到不產生改動。具體的體現其實與上面闡述的單一原則是一致的,既每一個類最好能做到只會被同一件事情影響和改變,其他類盡可能不受其影響。

類與類交互時,在滿足功能要求的基礎上,傳遞的數據量越少越好。因為這樣可能降低耦合度。

類與類的關系

泛化:子類與父類的關系,概念的復用,耦合度最高;

  B類泛化A類,意味B類是A類的一種;

  做法:B類繼承A

關於繼承關系,聲明一個父類,里面可以內置若干參數,若干方法,而之后聲明的子類,只要是繼承自這個父類,那么就可以直接獲取關於父類的參數和方法,除此之外,子

類還可以擁有自己專屬的額外參數和方法,這些新的參數和方法父類是不能享用的。

關聯(聚合/組合)部分與整體的關系,功能的復用,變化影響一個類;

   AB關聯,意味着BA的一部分;

  做法:在A類中包含B類型成員。

所謂的關聯關系,也被稱為聚合關系或者組合關系,指的是兩個類之間不做直接繼承,而是將一個類作為另一個類其中的一個參數進行連接。通過參數連接就避免了繼承必須繼承所有參數和方法的弊端,在耦合度上相對於繼承又下降了許多。

依賴:合作關系,一種相對松散的協作,變化影響一個方法;

   A類依賴B類,意味A類的某些功能靠B類實現;

  做法:B類型作為A類中方法的參數,並不是A的成員。

依賴關系,也被稱為合作關系,在關聯關系的基礎上進一步降低了耦合度,其中一個類的整體將只能作為另一個類的方法中的一個參數來進行調用。

所以對這三種關系進行耦合度排序的話:依賴關系耦合度最低 關聯關系耦合度適中 繼承關系耦合度相對最高。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM