設計原則------單一原則
如何理解單一職責原則
乙個類或者模組只負責完成乙個職責(或者功能)。
注意,這個原則描述的物件包含兩個,乙個是類(class),乙個是模組(module)關於這兩個概念,在專欄中,有兩種理解方式。一種理解是:把模組看作比類更加抽象的概念,類也可以看作模組。另一種理解是:把模組看作比類更加粗粒度的**塊,模組中包含多個類,多個類組成乙個模組。
單一職責原則的定義描述非常簡單,也不難理解。乙個類只負責完成乙個職責或者功能。也就是說,不要設計大而全的類,要設計粒度小、功能單一的類。換個角度來講就是,乙個類包含了兩個或者兩個以上業務不相干的功能,那我們就說它職責不夠單一,應該將它拆分成多個功能更加單如何判斷類的職責是否足夠單一?一、粒度更細的類。
我舉乙個例子來解釋一下。比如,乙個類裡既包含訂單的一些操作,又包含使用者的一些操作。而訂單和使用者是兩個獨立的業務領域模型,我們將兩個不相干的功能放到同乙個類中,那就違反了單一職責原則。為了滿足單一職責原則,我們需要將這個類拆分成兩個粒度更細、功能更加單一的兩個類:訂單類和使用者類
從剛剛這個例子來看,單一職責原則看似不難應用。那是因為我舉的這個例子比較極端,一眼就能看出訂單和使用者毫不相干。但大部分情況下,類裡的方法是歸為同一類功能,還是歸為不相關的兩類功能,並不是那麼容易判定的。在真實的軟體開發中,對於乙個類是否職責單一的判定,是很難拿捏的。我舉乙個更加貼近實際的例子來給你解釋一下。在乙個社交產品中,我們用下面的 userinfo 類來記錄使用者的資訊。你覺得,userinfo 類的設計是否滿足單一職責原則呢?
public class userinfo
對於這個問題,有兩種不同的觀點。一種觀點是,userinfo 類包含的都是跟使用者相關的資訊,所有的屬性和方法都隸屬於使用者這樣乙個業務模型,滿足單一職責原則;另一種觀點是,位址資訊在 userinfo 類中,所佔的比重比較高,可以繼續拆分成獨立的 useraddress 類,userinfo 只保留除 address 之外的其他資訊,拆分之後的兩個類的職責更加單一。不過,你可能還會有這樣的疑問:在上面的判定原則中,我提到類中的**行數、函式或者屬性過多,就有可能不滿足單一職責原則。那多少行**才算是行數過多呢?多少個函式、屬性才稱得上過多呢?哪種觀點更對呢?實際上,要從中做出選擇,我們不能脫離具體的應用場景。如果在這個社交產品中,使用者的位址資訊跟其他資訊一樣,只是單純地用來展示,那 userinfo 現在的設計就是合理的。但是,如果這個社交產品發展得比較好,之後又在產品中新增了電商的模組,使用者的位址資訊還會用在電商物流中,那我們最好將位址資訊從 userinfo 中拆分出來,獨立成使用者物流資訊(或者叫位址資訊、收貨資訊等)。
除此之外,從不同的業務層面去看待同乙個類的設計,對類是否職責單一,也會有不同的認識。比如,例子中的 userinfo 類。如果我們從「使用者」這個業務層面來看,userinfo 包含的資訊都屬於使用者,滿足職責單一原則。如果我們從更加細分的「使用者展示資訊」「位址資訊」「登入認證資訊」等等這些更細粒度的業務層面來看,那 userinfo 就應該繼續拆分。
綜上所述,評價乙個類的職責是否足夠單一,我們並沒有乙個非常明確的、可以量化的標準,可以說,這是件非常主觀、仁者見仁智者見智的事情。實際上,在真正的軟體開發中,我們也沒必要過於未雨綢繆,過度設計。所以,我們可以先寫乙個粗粒度的類,滿足業務需求。隨著業務的發展,如果粗粒度的類越來越龐大,**越來越多,這個時候,我們就可以將這個粗粒度的類,拆分成幾個更細粒度的類。這就是所謂的持續重構。
聽到這裡,你可能會說,這個原則如此含糊不清、模稜兩可,到底該如何拿捏才好啊?我這裡還有一些小技巧,能夠很好地幫你,從側面上判定乙個類的職責是否夠單一。而且,我個人覺得,下面這幾條判斷原則,比起很主觀地去思考類是否職責單一,要更有指導意義、更具有可執行性:
比較初級的工程師經常會問這類問題。實際上,這個問題並不好定量地回答,就像你問大廚「放鹽少許」中的「少許」是多少,大廚也很難告訴你乙個特別具體的量值。
如果繼續深究一下的話,你可能還會說,一些菜譜確實給出了,做某某菜需要放多少克鹽,放多少克油的具體量值啊。我想說的是,那是給家庭主婦用的,那不是給專業的大廚看的。模擬一下做飯,如果你是沒有太多專案經驗的程式設計初學者,實際上,我也可以給你乙個凑活能用、比較寬泛的、可量化的標準,那就是乙個類的**行數最好不能超過 200 行,函式個數及屬性個數都最好不要超過 10 個。
實際上, 從另乙個角度來看,當乙個類的**,讀起來讓你頭大了,實現某個功能時不知道該用哪個函式了,想用哪個函式翻半天都找不到了,只用到乙個小功能要引入整個類(類中包含很多無關此功能實現的函式)的時候,這就說明類的行數、函式、屬性過多了。實際上,等你做多專案了,**寫多了,在開發中慢慢「品嚐」,自然就知道什麼是「放鹽少許」了,這就是所謂的「專業第六感」。
設計原則 單一職責原則
定義 不要存在多於乙個導致類變更的原因。通俗的說,即乙個類只負責一項職責。問題由來 類t負責兩個不同的職責 職責p1,職責p2。當由於職責p1需求發生改變而需要修改類t時,有可能會導致原本執行正常的職責p2功能發生故障。解決方案 遵循單一職責原則。分別建立兩個類t1 t2,使t1完成職責p1功能,t...
設計原則 單一職責原則
1 原則的定義 2 原則設計的初衷 3 能解決哪些問題 4 有哪些場景可以使用 單一職責原則,英文名single responsibility principle,縮寫為srp。乙個類或者模組只負責完成乙個職責 或者功能 也就是說,不要設計大而全的類,要設計粒度小,功能單一的類。換個角度來講就是,乙...
設計原則 單一職責原則
在物件導向程式設計領域中,單一職責原則 single responsibility principle 規定每個類都應該有乙個單一的功能,並且該功能應該由這個類完全封裝起來。所有它的 這個類的 服務都應該嚴密的和該功能平行 功能平行,意味著沒有依賴 乙個類或者模組應該有且只有乙個改變的原因。乙個具體...