設計模式-面向對象基本原則之面向腎虧編程

前言

在我們日常的開發中,經常會遇到產品改需求、業務升級、刪除業務等等,就像傳說的朝三暮四(產品早上提了3個需求,下班就要驗收四個),這時候我們就不能和產品講道理,不能硬剛產品,畢竟剛了一天後,產品的需求定下來了,你的代碼卻一點都沒動。所以在寫代碼的時候,我們需要提高我們代碼的可擴展性、可維護性、低耦合,所以這也是我們需要學習設計模式的原因。當然,我們需要知道機器是不需要什麼設計模式的,它們只需要0和1,所以設計模式要以人爲本,我們的目的是團隊合作、產品升級。
那麼怎麼樣纔算設計模式呢,在面向對象中有六大基本原則,而這六個原則可以說是對一個好的設計模式的描述。

基本原則

單一職責原則(SRP)

從名字可以看出,一個類的功能最好是一個方向或一個類型的,也就是說不同的業務需要放在不同的類,這樣可以減少業務與業務之間的耦合,降低在一個業務作出修改的時候,對其他業務的影響。

以人爲例子,人由很多的器官組成,那人是一個類,腎、心臟也是一個單獨的類,他們有自己的功能如腎的排毒、心臟的血液循環。假設我們將腎和心都寫在了同一個類(器官類)中,那麼,當人生病了,腎虧了,那麼就要修改整個器官類,這一修改還有可能影響到了心臟的功能,那這樣多不好,一個器官的問題卻對所有的器官都進行了修改。如果我們將腎單獨寫一個類,那隻需要對腎進行修改就可以了,不影響到心臟和其他器官了。
當然,如果對腎進行手術,那此過程的藥物和流血對心臟和其他器官也是有影響的,所以我們的單一職責並不是說不能任何關係,而是儘量減小他們的關係,以此來減小相互的影響。

開閉原則(OCP)

對擴展是開放的,對修改是封閉的。在團隊開發中,我們經常會遇到,使用其他成員設計的的時候,某個功能點上是不符合你的需求,那麼此時,在原理上是不能對此類進行修改的,因爲此類已經制作好,若貿然修改會影響到原有的功能,所以,我們只能對此類進行擴展(使用繼承或依賴注入的方式),爲其添加一個新的功能,從而不影響到原有的功能。
這裏也有一個問題,就是擴展時,可能會遇到原有的類擴展性不高,很多東西都無法擴展,所以這裏就要求我們在編程的時候就要考慮到擴展性,不然每次遇到類似的業務,卻因爲某些小功能不一樣就要全部重寫。

以人爲例子,如果有一天你想變漂亮點,你可以去化妝、穿漂亮的衣服(依賴注入),當然這無法改變你的基因,你的小孩還是跟你一樣“醜”,此時,你可以在你孩子出生的後,給他喫好的穿好的,用多點護膚品之類的,那麼你的小孩就變得好看一些(繼承後,重寫一些類),當然如果依然很“醜”,這說明兩夫妻的基因實在有問題(原有的類,設計的很有問題,無法擴展了,只能重寫一個類)。
當然,有人認爲可以去整容,這裏的整容相當於依賴注入,因爲,他只是換了一張臉(換了一個表現形式),內部的邏輯並沒變,你還是那個“醜醜”的你。

里氏替換原則(LSP)

所有引用基類的地方,必須能透明的使用其子類對象。這裏主要體現的是抽象。在團隊開發中,我們經常會遇到,產品提了一個需求,要以a的形式表現,過了一陣子有覺得效果一般要換成b的,等b的上線後又覺得沒有a的好,要換回a。這裏如果不對功能進行抽象,那這裏一來一回的改動就很蛋疼了。一般的做法會將功能接口抽象出一個基類c,然後分別實現a和b,他們都繼承自這個抽象類c,那在產品需要改的時候就可以將實現切換即可。

以人爲例子,如果又腎虧了,而且到了要換腎的地步,此時,腎這個器官就相當於一個基類,而每個人的腎就是其子類,此時就可以用其他的子類來替換當前的子類。當然這裏需要配型,說明了不同的子類有不同的實現,表現也都不一樣,而配型是找其表現類似的子類,這樣才能替代其原來的實現(工作)

依賴倒置原則(DIP)

模塊間的依賴通過抽象發生,實現類之間不發生直接的依賴關係,其依賴關係是通過接口或抽象類產生。在團隊開發過程中,依賴是到處可見的,就和上一個原則中所說的a和b實現,切換的時候就要求使用其的模塊是依賴基類c(抽象接口或者抽象類),那麼此時直接將實現切換了就可以達到產品的要求,如果是直接依賴了實現a或b,那麼這裏改動的還有相關的方法,並且,如果調用了a特有的方法,就要對b進行修改,這裏就會增加不必要的工作量。

以人爲例子,如果人體的構造不依賴於腎的抽象,只關心輸入什麼給腎,然後拿到腎的輸出(腎的過濾功能),而是依賴於腎的具體實現,直接關心腎是怎麼過濾的,那麼我們在換腎的時候,身體就沒辦法使用到新的腎了(不是同一個類,調用不了方法),而且我們還有一些人工的機械腎,他們的實現就和人體的完全不一樣,如果人體過多的依賴於具體的實現,那麼未來就沒辦法使用到機械腎這種神器了。

接口隔離原則(ISP)

這個與單一職責有些類似,在我們依賴接口的時候,不應該依賴他不需要的接口。在團隊開發中,我們會遇到一些大接口,這些接口集合了多種功能,而使用的地方,分爲多個地方,但是每個地方其實只需要一種功能。那麼在使用的時候會導致接口過多的暴露,如果是自己剛寫的還好,如果是過了很久或者是其他人使用,有一眼看去這麼多接口方法,就導致很難使用,如果只暴露了一個功能,那麼使用者只看到自己需要的功能那就大大提高了接口的易用性,也減少了對其他功能耦合,提高團隊效率。而且在後期功能拆分的時候,可以更簡單的對大功能細分。

以人爲例子,人體的腎實現了腎功能的接口,那麼醫生在手術時,只需要關心腎就好了。但如果腎的接口不是腎功能接口,而是集合了肝功能,胃功能的接口,那麼在醫生手術的時候,除了看到腎的功能,還看到肝,等到切腎的時候,一不小心就把肝也切掉了。

迪米特原則(LOD)

一個類應該對自己需要耦合或調用的類知道得最少。在團隊開發中,經常會是一人開發一個功能,那麼有a功能、b功能、c功能(都是實現,或者都是接口),分別都是不同的人負責,當a需要使用到c的一個功能時,通過了b再去調用c,這裏就多了一個對的依賴,在後期維護的過程中,有人把b的改了,不用c這裏就會影響到a的功能。(當然如果b是一個統一管理或路由的類,負責轉發或者實現的選擇就不一樣了,但是這裏討論的是,三者都爲產品功能)

以人爲例子,人體的腎是使用腎小球來過濾血液,那麼如果調用腎小球過濾的方法在肝裏,腎在過濾的時候還需要調用到肝,然後在調用回腎,這裏的功能就變得複雜起來。在腎虧做腎移植手術的時候,在換了腎之後,接完腎的血管神經,還要把肝的連接接到腎上,這裏還有可能影響到了肝的功能。

小結

總的來說,人體的構造是經過了幾千幾億年的進化而來的,各個部分都十分強大、精細,該有的都會有,不該有的會慢慢淘汰(盲腸)。我們的代碼也一樣,該有的就需要有,不需要的統統都不要留下來(舊功能的備份使用git的記錄進行備份就好,最好不要用註釋的形式)。對於各種各樣的設計模式,我們學習這些模式不是爲了使用這些模式(當然學習最好的途徑是在使用中學習),而是要知道我們可以用什麼方法使我們的代碼變得符合6個基本原則。因爲不是每個設計模式都適合當前的項目、當前的功能,我們需要幾個多種設計模式甚至是使用自己想的模式來進行開發重構,以達到這個6個基本原則,並讓項目更具擴展性,可維護性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章