物件導向觀念

參考資料:(http://handsome-bridge.blogspot.com/2014/12/java.html)

不要自我重複(DRY:Don't Repeat Yourselt)

若有一部分的程式出現在不同地方 抽象化(Abstraction:將相同的邏輯往Parent搬) 委派(Delegation:將相同的任務委派給另一個物件 or 另一個method完成)

若有hard-code value重複出現 使用public final取代之,藉此可以提升維護性。

這個原則適用在相同功能,而不是相似的程式

這個原則很重要,但要小心不要濫用。範例去看參考資料。

將變動封裝起來(Encapsulate Changes)

軟體開發中唯一不變的就是"變動",變動可能來自於需求的改變、使用不同的工具。 要減少變動影響範圍,我們要將可能會變動的程式封裝起來。

利用封裝將細節隱藏起來,只提供主要介面供使用者驅動,若內部實作細節有任何異動,用戶端程式可以不用做任何異動。

封裝簡單來說,就是將變數、method盡可能private化。

若有段程式從 物件A get不同參數值,或呼叫 A 的不同method,很可能這段程式是屬於 A 的責任,你已經違反了封裝的概念。

不要小看封裝,若實作散落各地,實作內容變動愈大,所要修改的類別越多。

開放關閉設計原則(Open Close Design Principle)

開放:類別及方法要能夠擴充(加新功能 or 不同實作)

關閉:關閉修改(完成的程式不要再修改,refactoring例外)

要加入新功能,應該引入新的類別、方法、變數,而不是去修改既有已經完成測試的程式(避免修改造成的regression bug)。

但要如何使程式能夠擴充呢? 基本上,我們可以運用多型(polymorphism),藉由相同介面(interface 或 super class),讓我們可以在擴充行為時,不影響client端及既有程式。

單一責任原則(Single Responsibility Principle)

責任指的是變動的理由,一個類別應該只有一個變動的理由

例如一個類別負責編輯報表以及列印報表,這個類別就有兩個變動的理由: 資料的異動 報表的格式異動

將兩個不同責任綁在一起,除了會造成閱讀困難外,也會使其不好維護,畢竟我們不能保證修改其中一個功能,對另外一個不會造成影響。

相依性注入或反轉原則(Dependency Injection or Inversion Principle)

一般我們要使用一個物件,可能會直接 new 一個 instance,但DI告訴我們不要這樣,你應該動態注入相依的物件,這種方式可以帶來下面兩種好處:

1.讓我們在撰寫測試時,可以利用mock object,讓我們專注在該測的功能上。

2.可藉由修改設定檔注入不同實作(Polymorphism),而不必修改程式

傾向使用Composition多於繼承(Favor Composition over Inheritance)

使用繼承,我們將共同使用的程式碼移至super class 使用複合,我們將共同使用的程式碼移至composed class

兩者的差別在於彈性~

使用繼承,我們無法動態變更實作。 但是使用複合,我們可以藉由多型,讓不同實作有相同介面,藉由執行期的相依性注入抽換不同實作,任何時候我們都可以切換不同實作,而不用改程式。

額外參考資料:(https://tw.twincl.com/programming/*662v)

繼承 inheritance is a 複合 composition has a

favor composition over inheritance

繼承在揉麵團、麵條的時候,比較簡單快速,但倘若程式持續發展,就會越來越難搞。

複合可能會在一開始下比較多工夫,

但是對於之後的彈性、可讀性,會比較好。 而可讀性較好,也就比較不容易有bug,因為工程師越容易看懂,就不會誤用而產生bug。

因為複合架構並不會有 protected & virtual 成員,所以界線會比較清楚,可以避免類別之間纏繞在一起。 雖然複合並不會使問題神奇的自動消失,但確實會讓程式碼保持在比較簡單的狀態 ~

理論上,採用繼承也可以保持類別分開,但現實上很難維持,而複合則強迫我們做到這一點。

繼承有機會導致 菱形問題 ,雖然JAVA不會遇到,有興趣可以去參考資料內了解一下。

介面分離原則(ISP:Interface Segregation Principle)

這個原則是指 Client 不應實作一個他不提供的功能介面。 會違反這個原則,通常代表該介面負責了超過一個功能 (違反單一責任原則) ,而Client只需要部分功能。

在介面的設計上必須非常小心,因為一但發布了,日後所做的修改都會使現有的實作無法運行。

Liskov 替換原則(Liskov Substitution Principle)

這個原則指的是 子類別的實作必須可以代替父類別 換句話說,父類別有的,子類別都要有。 子類別只能擴充、增加,不能減少父類別的功能。

LSP & 單一責任原則 & 介面分離原則 有很強的關聯。 若一個類別有太多功能,子類別就無法支援所有行為。

因為多型開發時操作的都是 super class 或 interface,違反此原則就會帶來錯誤的結果。

針對介面而非實作(Programming for interface not implementation)

這個原則是要我們善用多型,定義變數或方法變數或回傳變數時,使用介面而非實作,這種做法可以帶來彈性。 當要替換實作時,這樣可以讓你減少異動。

委派原則(Delegation Principle)

不要試著在一個類別中做所有的事,把責任委派給該負責的類別。

EX:hash code 和 equals method

要比較兩個物件是否相同,不應該在Client端寫程式,而是交由物件本身去比較。 這樣的好處是可以減少重複的程式碼,讓系統更好維護。

Last updated