首先呢,我們來看一下單一職責原則的定義。
就乙個類而言,應該只有乙個引起它變化的原因
這個說法不是很好懂,有一些抽象,不過呢,我們依舊可以嘗試著理解一下。
就乙個類而言,只有乙個引起它變化的原因,也就是說,除此之外,不能有其它引起變化的原因。
這樣就需要乙個前提,這個類只能負責一項職責,而不能負責其他的職責,不然,其他的職責就會存在其他變化的原因了。
通俗的說,即乙個類只負責一項職責。
懶人就比較喜歡這種通俗地定義,一目了然。
懶人曾經總結過:通俗的定義,淺顯易懂;理論的定義,大腦一懵。
有同感的小夥伴請雙擊666。
餐館聚餐,通過服務員點餐
這樣乙個服務員為我們點餐的場景,一般都是什麼樣的流程?
第一步:客人點餐
懶人:咱呢,不但要吃飽,還要吃好!服務員,先來乙份西紅柿炒雞蛋,再來乙份酸辣土豆絲!!!
好友:臉呢。。。說好的臉呢。。。
服務員:你是顧客,你是上帝,你說啥就是啥,不過,你剛才說的是啥。。。
第二步:烹飪美食
西紅柿炒雞蛋,先炒雞蛋,再炒西紅柿。。。ok,出鍋。
第三步:上餐
服務員:這是您點的西紅柿炒雞蛋,請您慢用。
不廢話,擼**。
package com.fanqiekt.principle.single;
/*** 服務員
* @author: 番茄課堂-懶人
*/public class waiter
system.out.println(dishname + "出鍋");
system.out.println(dishname + "上桌啦,請您品嚐");}}
服務員這個模擬較簡單,就乙個下單的方法。
為了更好的理解,懶人進行了細節的優化(主要是很多細節懶人壓根不了解)。
package com.fanqiekt.principle.single;
/** * 客戶端
* @author: 番茄課堂-懶人
*/public class client
}
客戶端這個類就相當於客人,客人負責通過服務員點餐。
客人一共點了兩道大餐,西紅柿炒雞蛋、酸辣土豆絲,我們來執行一下,看看結果。
客人點餐:西紅柿炒雞蛋
開始烹飪:西紅柿炒雞蛋
先炒雞蛋
再炒西紅柿
...西紅柿炒雞蛋出鍋
西紅柿炒雞蛋上桌啦,請您品嚐
-------
客人點餐:酸辣土豆絲
開始烹飪:酸辣土豆絲
先放蔥薑蒜
再放土豆絲
...酸辣土豆絲出鍋
酸辣土豆絲上桌啦,請您品嚐
ok,兩個熱氣騰騰的飯菜就做好了。
我們回過頭來看一下waiter類,大家覺得這個類好不好?
肯定是不好了,那…不好在**?
這就好比乙個小作坊,老闆既負責點餐又負責下單,就跟waiter類一樣。
我們一般在小作坊吃飯,感受會怎麼樣?
亂,非同一般的雜亂。上菜需要等半天,點餐的時候找不到人。
還有乙個弊端,我修改了做飯的流程,會影響下單的業務,增加修改的風險,為什麼這麼說呢?
客人a:老闆,給我來乙份酸辣土豆絲。
老闆:好嘞,您稍等。
懶人:老闆,我剛才點的西紅柿雞蛋要少放鹽啊。
老闆:好的,我放鹽的時候用小點的勺子。
客人a:老闆,我的菜做了嗎?我的同伴都吃完了,沒做我就不要了!
老闆:您的菜已經做了,馬上就要出鍋了。(內心:我勒個去,剛才用小勺放鹽的時候把這哥們點的單給忘了,這就尷尬了。。。)
不難看出,當功能冗雜到乙個物件中,這樣修改就會增加風險。那我們該如何避免呢?
一般比較完善的餐館,還至少會有一名廚師。
廚師做飯,服務員點餐,這樣做,有什麼好處呢?
一來,結構清晰了,各司其職,一目了然。二來,風險降低了,我修改做飯的流程,不會影響下單的業務。
只負責一項職責,這就是單一職責原則。
那我們嘗試著增加乙個廚師類。
package com.fanqiekt.principle.single;
/** * 廚師
* * @author 番茄課堂-懶人
*/public class chef
system.out.println(dishname + "出鍋");}}
廚師類,只負責了一項職責:做飯。
這就是類的單一職責原則。
chef類只有乙個cooking方法,cooking方法是根據下單的菜品名稱去烹飪不同的菜,以及炒西紅柿雞蛋以及酸辣土豆絲的具體烹飪過程。這樣做合適嗎?
不合適的,cooking方法應該只有菜品分發這一項職責,而炒西紅柿雞蛋以及酸辣土豆絲這兩件事顯然易見與分發沒有任何關係,所以拆分出來效果會更好。
我們將廚師類再優化下。
package com.fanqiekt.principle.single;
/** * 廚師
* * @author 番茄課堂-懶人
*/public class chef
system.out.println(dishname + "出鍋");
}/**
* 炒西紅柿雞蛋
*/private void cookingtomato()
/*** 炒酸辣土豆絲
*/private void cookingpotato()
}
優化後chef類有三個方法。
cooking方法是根據下單的菜品名稱去烹飪不同的菜。
cookingtomato方法是炒西紅柿雞蛋。
cookingpotato方法是炒酸辣土豆絲。
每個方法只負責一項職責,這就是方法的單一職責原則。
遵守方法單一職責原則的類,是不是更加的直觀?修改各自的方法是不是也沒有影響到其他的方法?
接下來,我們再優化下waiter類,讓他遵循類的單一職責原則。
package com.fanqiekt.principle.single;
/** * 單一職責原則的服務員
* * @author 番茄課堂-懶人
*/public class waiter
}
優化後singlewaiter類有只負責點餐、上餐這些與服務員相關的職責,而做飯的這些無關的職責則交給了chef。
遵守類單一職責原則的專案,是不是更加的直觀?修改各自的類是不是也沒有影響到其他的類?
接下來,我們把client執行一下。
客人點餐:西紅柿炒雞蛋
開始烹飪:西紅柿炒雞蛋
先炒雞蛋
再炒西紅柿
...西紅柿炒雞蛋出鍋
西紅柿炒雞蛋上桌啦,請您品嚐
-------
客人點餐:酸辣土豆絲
開始烹飪:酸辣土豆絲
先放蔥薑蒜
再放土豆絲
...酸辣土豆絲出鍋
酸辣土豆絲上桌啦,請您品嚐
結果與原來一致。
擼過**後,我們發現單一職責原則的幾個優點。
提高類的可讀性
符合單一職責原則的方法、類,結構會更加的清晰,類的可讀性也就提高了。
降低類的複雜性
乙個類只負責一項職責,乙個方法也只負責一項職責。肯定要比功能冗雜到乙個方法,乙個類中要簡單得多。
降低風險
修改其中的乙個業務,不會影響到業務。
我們必須要意識到,一味的遵守單一職責原則,不停的分拆類所付出的開銷是很大的。
這時候就涉及到平衡的問題,平衡單一職責原則與修改造成的開銷。
懶人的觀點是如果乙個方法邏輯不複雜的情況下,可以修改方法實現,否則要拆分為兩個方法,遵循方法級別的單一職責原則。
如果乙個類方法不多的情況下,可以只增加方法,而不用分拆為多個類,否則要拆分為多個類,遵循類級別的單一職責原則。
接下來,請您欣賞單一職責原則的原創歌曲。
嘻哈說:單一職責原則
作曲:懶人
作詞:懶人
週末約上了好友去熟悉的餐館聚餐
只負責點餐的漂亮服務員保持笑容已經成為習慣
只負責做飯的帥氣廚師一直待在了煙霧瀰漫了幾遍的廚房裡面
每個人有自己負責的地盤
就像單一職責
乙個類只有乙個職責 好體面
它降低了類的複雜性
它提高了類的可讀性
那風險被降低代表著單一職責沒毛病
試聽這裡閒來無事聽聽曲,知識已填腦中去;
學習複習新方式,頭戴耳機不小覷。
番茄課堂,學習也要酷。
嘻哈說 設計模式之介面隔離原則
按照慣例,首先我們來看一下介面隔離原則的定義。類間的依賴關係應該建立在最小的介面上。介面中的方法應該盡量少,不要使介面過於臃腫,不要有很多不相關的邏輯方法。有點類似於單一職責原則,都是功能盡可能的簡單單一,不要冗餘太多其他不相關的。單一職責原則主要是類與方法,而介面隔離原則卻是對介面而言的。小廚洗菜...
設計模式之單一職責原則
關於單一職責原則,我想大家都聽過不少,今天來看看這個原則具體是什麼,有哪些好處使我們需要選擇遵守它呢?一 定義 乙個類只能因為乙個原因而修改。怎麼理解呢?簡單來說,乙個類只能實現一項功能,或者換句話說,乙個類只有乙個職責,只有當這個職責發生變化,它才會被修改,說白了就是乙個類質感乙個類該幹的事。二 ...
設計模式之單一職責原則
首先就名字而言不難想象,單一必定是只能有乙個,而這個乙個指的是什麼呢,那就是乙個職責。而職責通俗易懂來說就是乙個功能,乙個類只能有乙個功能,而如果有兩個及以上的功能就不再符合單一職責原則了。就好比乙個水壺,它的功能就只是裝水,而不存放別的東西,那它就滿足了單一職責原則。優點有複雜度低,或者說簡單明瞭...