您好,登錄后才能下訂單哦!
這篇文章主要介紹了面向?qū)ο笤O計原則中SRP的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
做開發(fā)到現(xiàn)在,相信大家已經(jīng)聽到過這樣的說法:"類的職責越單一,越容易重用。"這話怎么理解呢?我舉個例子,校驗碼。設想你現(xiàn)在拿到一個任務就是實現(xiàn)我們系統(tǒng)中的登錄模塊的校驗碼功能,你怎么做?我覺得我們大部分開發(fā)人員都會做下面這樣的設計(當然更壞的是有人干脆寫一個工具類,提供一個靜態(tài)的generateVerifyCode方法):
這個設計有什么問題呢?有接口有實現(xiàn),貌似夠合理了。我們拿實際發(fā)生的事來看夠不夠合理――我們系統(tǒng)剛上線的時候校驗碼的實現(xiàn)沒有現(xiàn)在這樣花哨,那個時候只是白色背景加上一組沒有經(jīng)過扭曲處理的數(shù)字;但是后來需求進化了,因為原來的校驗碼可能會被破譯,所以需要對數(shù)字進行扭曲,而且不能只產(chǎn)生數(shù)字,還要有字母,以增加破譯的難度。這時我們怎么辦?基于上面的設計,就需要修改VerifyCodeGeneratorImpl類(注意:即使在這種不合理的設計下,修改實現(xiàn)也是不好的做法,倒不如丟棄這個實現(xiàn),新增一個實現(xiàn)),修改其中產(chǎn)生隨機數(shù)的代碼,并且在生成圖片的時候?qū)Ξa(chǎn)生的隨機文本添加扭曲處理邏輯。因為需求的變化而修改代碼, 這說明原來的設計是不好的,違反了面向?qū)ο笤O計的另外一個原則"開放封閉原則(OCP)",這個原則另外再談,主要就是說一個類(或者模塊)只可以擴展,但不可修改。
細分析可以看出,導致實現(xiàn)類需要做修改的原因是:它承擔了兩個本應該分離的職責――產(chǎn)生隨機文本和生成校驗碼圖片。好,我們嘗試將產(chǎn)生隨機文本的職責分離出來,設計如下:
在這樣的設計下, 校驗碼隨機文本的生成職責被分離成一個單獨的演化體系,隨著需求的變化可以添加產(chǎn)生漢字隨機文本之類的新實現(xiàn),并且不影響校驗碼的顯示。但這個設計還沒有滿足需求的變更,因為現(xiàn)在的需求是不光隨機文本內(nèi)容從純數(shù)字變成了數(shù)字加字母,而且要求顯示的時候?qū)?shù)字進行扭曲,在這個設計中,我們可以添加新的VerifyCodeGenerator實現(xiàn)如TransformedVerifyCodeGeneratorImpl以替換原來的VerifyCodeGeneratorImpl。這樣做可行,但還有更好點的設計,如下:
這樣做,把圖片的生成職責也單獨抽象成一個演化體系,這樣以來,將來如果需要在顯示校驗碼時加上背景色或者背景噪音,只需要添加新的ImageGenerator實現(xiàn)。而且ImageGenerator作為一個通用的類,可以被其他有相應生成圖片需求的類所重用而不是只局限于生成校驗碼。上面的設計配合Spring的依賴注入,我們可以生成N * M種校驗碼(N是RandomTextGenerator的實現(xiàn)類數(shù),M是ImageGenerator的實現(xiàn)類數(shù)),而基于最初的設計,我們就需要創(chuàng)建N*M個VerifyCodeGenerator的實現(xiàn)類,且這些實現(xiàn)類可復用性很低。
從上面例子的探討中可以得出這么一個結(jié)論:一個類(或者大到模塊,小到方法)承擔的職責越多,它被復用的可能性越小。這就是單一職責原則(SRP)要表述的內(nèi)容:就一個類而言,應該僅有一個引起它變化的原因。
本著這個原則,我們再看一個常見的DAO設計:
interface DAO{ Connection connect(); void close(); void executeUpdate(); ResultSet executeQuery(String sql); }
這個接口有什么問題沒有,好像很多人都這么干。只要設想一下如果底層數(shù)據(jù)庫變化了,connect方法的代碼就可能需要改變(有人說我們不需要改變,那是因為我們使用了Spring提供的DataSource抽象隔離了取得數(shù)據(jù)庫鏈接的變化)。這個接口包含了兩個職責:數(shù)據(jù)庫鏈接管理和數(shù)據(jù)操作。
在實際操作中,如何識別職責是一個說起來容易做起來難的問題,比如有人可能會說,"產(chǎn)生校驗碼圖片"本身就是一個獨立職責呀,我說是的,如果我們的校驗碼圖片一成不變,最初的那個設計不算很壞,只不過喪失了一點重用性而已(比如產(chǎn)生隨機文本的邏輯可能被其他的模塊重用),但是需求后來變化了,不能只顯示數(shù)字,還要字母,這說明產(chǎn)生隨機文本是一個變化緯度,將來很可能還有新的變化,那就應該把這個職責獨立出來;需求又說顯示的文本需要扭曲,這說明圖片的生成也是一個變化緯度,沿著這個緯度將來很可能也有新的變化,那就也應該把這個職責獨立出來。需求變化所影響的變化緯度,往往就是應該被獨立的職責。所以如果你接到一個需求后發(fā)現(xiàn)需要修改一個已經(jīng)存在的類,那就要考慮一下是不是原來的設計不合理,沒有把應該獨立出來的職責分離出來。需求變化結(jié)合經(jīng)驗、常識,就可以慢慢識別職責應該分到什么粒度了。
單一職責原則不光對類設計有意義,對以模塊、子系統(tǒng)為單位的架構(gòu)設計一樣有意義,一個模塊、子系統(tǒng)也應該僅有一個引起它變化的原因,不同的是模塊和子系統(tǒng)承擔的職責粒度跟類相比是另外一個層次了。
如果讓我列舉一下一個良好的設計應該具備的素質(zhì),我會說:高內(nèi)聚,低耦合。單一職責原則正是實現(xiàn)高內(nèi)聚低耦合需要遵守的一個原則。
感謝你能夠認真閱讀完這篇文章,希望小編分享的“面向?qū)ο笤O計原則中SRP的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學習!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。