1 oo的設計原則
採用物件導向的分析和設計思想,為我們分析和解決問題提供了一種全新的思維方式。我們在拿到需求之後(略去ooa,以後補全),接下來的問題就是:如何對系統進行物件導向的設計呢?
按照軟體工程的理論,物件導向的設計要解決的核心問題就是可維護性和可復用性,尤其是可維護性,它是影響軟體生命週期重要因素。通常情況下,軟體的維護成本遠遠大於初期開發成本。
乙個可維護性很差的軟體設計,人們通常稱之為「臭味」的,形成的原因主要有這麼幾個:過於僵硬、過於脆弱、復用率低或者黏度過高。相反,乙個好的系統設計應該是靈活的、可擴充套件的、可復用的、可插拔的。在20世紀80到90年代,很多業內專家不斷探索物件導向的軟體設計方法,陸續提出了一些設計原則。這些設計原則能夠顯著地提高系統的可維護性和可復用性,成為了我們進行物件導向設計的指導原則:
1、單一職責原則srp
每乙個類應該專注於做一件事情。
2、「開-閉」原則ocp
每乙個類應該是對擴充套件開放,對修改關閉。
3、 黎克特制代換原則lsp
避免造成派生類的方法非法或退化,乙個基類的使用者應當不需要知道這個派生類。
4、 依賴倒轉原則dip
用依賴於介面和抽象類來替代依賴容易變化的具體類。
5、 介面隔離原則isp
應當為客戶提供盡可能小的介面,而不是提供大的介面。
其中,「開-閉」原則是物件導向的可復用設計的基石,其他設計原則(黎克特制代換原則、依賴倒轉原則、合成/聚合復用原則、迪公尺特法則、介面隔離原則)是實現「開-閉」原則的手段和工具。
我會為大家一一進行講解。
2 單一職責原則srp(single-responsibility principle)
2.1 什麼是單一職責
單一職責就是指乙個類應該專注於做一件事。現實生活中也存在諸如此類的問題:「乙個人可能身兼數職,甚至於這些職責彼此關係不大,那麼他可能無法做好所有職責內的事情,所以,還是專人專管比較好。」我們在設計類的時候,就應該遵循這個單一職責原則。
記得有人比喻過軟體開發、設計原則、設計模式之間的關係就是戰爭、戰略和戰術的關係,關於設計模式實際上是設計原則的具體應用,以後我們還會講到這一點。另外,大家都很熟悉計算器的例子,很多的人都願意以此為例,我們也以計算器程式設計為例說明單一職責原則:
在有些人眼裡,計算器就是一件東西,是乙個整體,所以它把這個需求進行了抽象,最終設計為乙個calculator類,**如下:
class calculator
else if (stropr == "-")
else if (stropr == "*")
else if (stropr == "/")
console.writeline("the result is " + strresult);
}
}另外,還有一部分人認為:計算器是乙個外殼和乙個處理器的組合。
console.write("please input the second number:");
strnum2 = console.readline();
return 0;
}public string displayoutput(string strresult)
}class processor
else if (stropr == "-")
else if (stropr == "*")
else if (stropr == "/")
return strresult;}}
我們再舉乙個郵件的例子。我們平常收到的郵件內容,看起來是一封信,實際上內部有兩部分組成:郵件頭和郵件體。電子郵件的編碼要求符合rfc822標準。
第一種設計方式是這樣:
inte***ce iemail
class email implements iemail
public void setreceiver(string receiver)
public void setcontent(string content)
}這個設計是有問題的,因為郵件頭和郵件體都有變化的可能性。
1、郵件頭的每乙個域的編碼,可能是base64,也可能是qp,而且域的數量也不固定。
2、郵件體中封裝的郵件內容可能是plaintext型別,也可能是html型別,甚至於流**。
所謂第一種設計方式違背了單一職責原則,裡面封裝了兩種可能引起變化的原因。
我們依照單一職責原則,對其進行改進後,變為第二種設計方式:
inte***ce iemail
inte***ce icontent
class email implements iemail
public void setreceiver(string receiver)
public void setcontent(icontent content)
}有的資料把單一職責解釋為:「僅有乙個引起它變化的原因」。這個解釋跟「專注於做一件事」是等價的。如果乙個類同時做兩件事情,那麼這兩件事情都有可能引起它的變化。同樣的道理,如果僅有乙個引起它變化的原因,那麼這個類也就只能做一件事情。
2.2 單一職責原則的使用
單一職責原則的尺度如何掌握?我們怎麼能知道該拆分還是不應該拆分呢?原則很簡單:需求決定。如果你所需要的計算器,永遠都沒有外觀和處理器變動的可能性,那麼就應該把它抽象為乙個整體的計算器;如果你所需要的計算器,外殼和處理器都有可能發生變動,那麼就必須把它拆離為外殼和處理器。
單一職責原則實際上是把相同的職責進行了聚合,避免把相同的職責分散到不同的類之中,這樣就可以控制變化,把變化限制在乙個地方,防止因為乙個地方的變動,引起更多地方的變動的「漣漪效應」,單一職責原則避免乙個類承擔過多的職責。單一職責原則不是說乙個類就只有乙個方法,而是具有單一功能。
我們在使用單一職責原則的時候,牢記以下幾點:
a、乙個設計合理的類,應該僅有乙個可以引起它變化的原因,即單一職責,如果有多個原因可以引起它的變化,就必須進行分離;
b、在沒有需求變化徵兆的情況下,應用單一職責原則或其他原則是不明智的,因為這樣會使系統變得很複雜,系統將會變成一堆細小的顆粒組成,純屬於沒事找抽;
c、在需求能夠預計或實際發生變化時,就應該使用單一職責原則來重構**,有經驗的設計師、架構師對可能出現的需求變化很敏感,設計上就會具有一定的前瞻性。
架構師之路 4 詳解物件導向
3.5 詳解物件導向的程式設計 oop 3.5.1 什麼是物件導向 剛接觸程式設計的時候,多數人本能的反映可能是面向過程 op 的,而不是物件導向 oo 的。這種現象其實是很正常的,改變思維方式是需要乙個過程的,我大體歸納了一下其形成的原因 1 直接原因 你還沒有養成物件導向分析問題和解決問題的習慣...
架構師之路 1 面向過程和物件導向
1 引言 機算機科學是一門應用科學,它的知識體系是典型的倒三角結構,所用的基礎知識並不多,只是隨著應用領域和方向的不同,產生了很多的分支,所以說程式設計並不是一件很困難的事情,乙個高中生經過特定的訓練就可以做得到。但是,會程式設計和編好程絕對是兩碼事,同樣的程式設計師,有的人幾年之後成為了架構師,有...
架構師之路 1 面向過程和物件導向
1 引言 機算機科學是一門應用科學,它的知識體系是典型的倒三角結構,所用的基礎知識並不多,只是隨著應用領域和方向的不同,產生了很多的分支,所以說程式設計並不是一件很困難的事情,乙個高中生經過特定的訓練就可以做得到。但是,會程式設計和編好程絕對是兩碼事,同樣的程式設計師,有的人幾年之後成為了架構師,有...