天天看點

《Android 源碼設計模式解析與實戰》——第1章,第1.1節優化代碼的第一步——單一職責原則

本節書摘來自異步社群《android 源碼設計模式解析與實戰》一書中的第1章,第1.1節優化代碼的第一步——單一職責原則,作者 何紅輝 , 關愛民,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視

第1章 走向靈活軟體之路——面向對象的六大原則

android 源碼設計模式解析與實戰

1.1 優化代碼的第一步——單一職責原則

單一職責原則的英文名稱是single responsibility principle,縮寫是srp。srp的定義是:就一個類而言,應該僅有一個引起它變化的原因。簡單來說,一個類中應該是一組相關性很高的函數、資料的封裝。就像老師在《設計模式之禅》中說的:“這是一個備受争議卻又及其重要的原則。隻要你想和别人争執、怄氣或者是吵架,這個原則是屢試不爽的”。因為單一職責的劃分界限并不是總是那麼清晰,很多時候都是需要靠個人經驗來界定。當然,最大的問題就是對職責的定義,什麼是類的職責,以及怎麼劃分類的職責。

對于計算機技術,通常隻單純地學習理論知識并不能很好地領會其深意,隻有自己動手實踐,并在實際運用中發現問題、解決問題、思考問題,才能夠将知識吸收到自己的腦海中。下面以我的朋友小民的事情說起。

自從android系統釋出以來,小民就是android的鐵杆粉絲,于是在大學期間一直保持着對android的關注,并且利用課餘時間做些小項目,鍛煉自己的實戰能力。畢業後,小民如願地加入了心儀的公司,并且投入到了他熱愛的android應用開發行業中。将愛好、生活、事業融為一體,小民的第一份工作也算是順風順水,一切盡在掌握中。

在經曆過一周的适應期以及熟悉公司的産品、開發規範之後,小民的開發工作就正式開始了。小民的主管是個工作經驗豐富的技術專家,對于小民的工作并不是很滿意,尤其小民最薄弱的面向對象設計,而android開發又是使用java語言,程式中的抽象、接口、六大原則、23種設計模式等名詞把小民弄得暈頭轉向。小民自己也察覺到了自己的問題所在,于是,小民的主管決定先讓小民做一個小項目來鍛煉這方面的能力。正所謂養兵千日用兵一時,磨刀不誤砍柴工,小民的開發之路才剛剛開始。

在經過一番思考之後,主管挑選了使用範圍廣、難度也适中的圖檔加載器(imageloader)作為小民的訓練項目。既然要訓練小民的面向對象設計,那麼就必須考慮到可擴充性、靈活性,而檢測這一切是否符合需求的最好途徑就是開源。使用者不斷地提出需求、回報問題,小民的項目需要不斷更新以滿足使用者需求,并且要保證系統的穩定性、靈活性。在主管跟小民說了這一特殊任務之後,小民第一次感到了壓力,“生活不容易!”年僅22歲的小民發出了如此深刻的感歎!

挑戰總是要面對的,何況是從來不服輸的小民。主管的要求很簡單,要小民實作圖檔加載,并且要将圖檔緩存起來。在分析了需求之後,小民一下就放心下來了,“這麼簡單,原來我還以為很難呢……”小民胸有成足地喃喃自語。在經曆了10分鐘的編碼之後,小民寫下了如下代碼:

并且使用git軟體進行版本控制,将工程托管到github上,伴随着git push指令的完成,小民的imageloader 0.1版本就正式釋出了!如此短的時間内就完成了這個任務,而且還是一個開源項目,小民暗暗自喜,并幻想着待會兒被主管稱贊。

在小民給主管報告了imageloader的釋出消息的幾分鐘之後,主管就把小民叫到了會議室。這下小民納悶了,怎麼誇人還需要到會議室。“小民,你的imageloader耦合太嚴重啦!簡直就沒有設計可言,更不要說擴充性、靈活性了。所有的功能都寫在一個類裡怎麼行呢,這樣随着功能的增多,imageloader類會越來越大,代碼也越來越複雜,圖檔加載系統就越來越脆弱……”這簡直就是當頭棒喝,小民的腦海裡已經聽不清主管下面說的内容了,隻是覺得自己之前沒有考慮清楚就匆匆忙忙完成任務,而且把任務想得太簡單了。

“你還是把imageloader拆分一下,把各個功能獨立出來,讓它們滿足單一職責原則。”主管最後說道。小民是個聰明人,敏銳地捕捉到了單一職責原則這個關鍵詞,他用google搜尋了一些資料之後,總算是對單一職責原則有了一些認識,于是打算對imageloader進行一次重構。這次小民不敢過于草率,也是先畫了一幅uml圖,如圖1-1所示。

《Android 源碼設計模式解析與實戰》——第1章,第1.1節優化代碼的第一步——單一職責原則

imageloader代碼修改如下所示:

如圖1-1和上述代碼所示,小民将imageloader一拆為二,imageloader隻負責圖檔加載的邏輯,而imagecache隻負責處理圖檔緩存的邏輯,這樣imageloader的代碼量變少了,職責也清晰了;當與緩存相關的邏輯需要改變時,不需要修改imageloader類,而圖檔加載的邏輯需要修改時也不會影響到緩存處理邏輯。主管在稽核了小民的第一次重構之後,對小民的工作給予了表揚,大緻意思是結構變得清晰了許多,但是可擴充性還是比較欠缺。雖然沒有得到主管的完全肯定,但也是頗有進步,再考慮到自己确實有所收獲,小民原本沮喪的心裡也略微地好轉起來。

從上述的例子中我們能夠體會到,單一職責所表達出的用意就是“單一”二字。正如上文所說,如何劃分一個類、一個函數的職責,每個人都有自己的看法,這需要根據個人經驗、具體的業務邏輯而定。但是,它也有一些基本的指導原則,例如,兩個完全不一樣的功能就不應該放在一個類中。一個類中應該是一組相關性很高的函數、資料的封裝。工程師可以不斷地審視自己的代碼,根據具體的業務、功能對類進行相應的拆分,這是程式員優化代碼邁出的第一步。

繼續閱讀