# 單一職責原則
# 單一職責原則的定義是就一個類別而言,應該僅有一個引起他變化的原因。也就是說一個類別應該只負責一件事情。如果一個類別負責了方法M1,方法M2兩個不同的事情,當M1方法改變的時候,我們需要修改這個類別的M1方法,但是這個時候就有可能導致M2方法不能運作。這不是我們期待的,但由於這種設計很有可能發生。所以這時候,我們需要把M1方法,M2方法單獨分離成兩個類別。讓每個類別只專心處理自己的方法。
單一職責原則的好處如下:
可以降低類別的複雜度,一個類別只負責一項職責,這樣邏輯也簡單很多提高類別的可讀性,和系統的維護性,因為不會有其他奇怪的方法來幹擾我們理解這個類別的含義當改變的時候,能將變化的影響降到最小,因為只會在這個類別中做出修改。
開閉原則
# 開閉原則和單一職責原則一樣,是非常基礎而且一般是常識的原則。開閉原則的定義是軟體中的物件(類,模組,函數等)應該對於擴展是開放的,但是對於修改是關閉的。
當需求改變的時候,我們需要對程式碼進行修改,這個時候我們應該盡量去擴展原來的程式碼,而不是去修改原來的程式碼,因為這樣可能會引起更多的問題。
這個準則和單一職責原則一樣,是一個大家都這樣去認為但是又沒規定具體該如何去做的一種原則。
開閉原則我們可以用一種方式來確保他,我們用抽象去建構框架,用實作擴充細節。這樣當修改發生的時候,我們就直接用抽象了衍生一個具體類別去實作修改。
里氏替換原則
# 里氏替換原則是一個非常有用的一個概念。他的定義
如果對每一個類型為T1的物件o1,都有類型為T2的物件o2,使得以T1定義的所有程式P在所有物件o1都替換成o2的時候,程式P的行為都沒有發生變化,那麼類型T2是類型T1的子類型。
這樣說有點複雜,其實有一個簡單的定義
# 所有引用基底類別的地方必須能夠透明地使用其子類別的物件。
里氏替換原則通俗的去講就是:子類別可以去擴展父類別的功能,但是不能改變父類原有的功能。他包含以下幾層意思:
子類別可以實作父類別的抽象方法,但是不能覆寫父類別的非抽象方法。
子類可以增加自己獨有的方法。
當子類別的方法重載父類別的方法時候,方法的形參要比父類別的方法的輸入參數更寬鬆。
當子類別的方法實作父類別的抽象方法時,方法的傳回值比父類別更嚴格。
里氏替換原則之所以這樣要求是因為繼承有很多缺點,他雖然是複用代碼的一種方法,但同時繼承在一定程度上違反了封裝。父類別的屬性和方法對子類別都是透明的,子類別可以隨意修改父類別的成員。這也導致了,如果需求變更,子類別對父類別的方法進行一些複寫的時候,其他的子類別無法正常運作。所以里氏替換法則被提出來。
確保程序遵循里氏替換原則可以要求我們的程序建立抽象,透過抽象去建立規範,然後用實現去擴展細節,這個是不是很耳熟,對,里氏替換原則和開閉原則往往是相互依存的。
依賴倒置原則
# 依賴倒置原則指的是一種特殊的解耦方式,使得高層次的模組不應該依賴低層次的模組的實現細節的目的,依賴模組被顛倒了。這也是一個讓人難懂的定義,他可以簡單來說就是
高層模組不應該依賴底層模組,兩者都應該依賴其抽象 抽像不應該依賴細節 細節應該依賴抽象
# 在Java 中抽象指的是介面或抽象類,兩者皆不能實例化。而細節就是實作類,也就是實作了介面或是繼承了抽象類別的類別。他是可以被實例化的。高層模組指的是呼叫端,底層模組是具體的實作類別。在Java中,依賴倒置原則是指模組間的依賴是透過抽象化來發生的,實作類別之間不會發生直接的依賴關係,其依賴關係是透過介面是來實現的。這就是俗稱的面向介面程式設計。
我們下面有一個例子來講述這個問題。這個例子是工人用錘子來修理東西。我們的程式碼如下:
public class Hammer {
public String function(){
# return "用鐵鎚修理東西";
# }
# }
# public class Worker {
public void fix(Hammer hammer){
System.out.println("工人" hammer.function());
}
# public static void main(String[] args) {
# new Worker()。 fix(new Hammer());
# }
# }
# 這個是一個很簡單的例子,但是如果我們要新增加一個功能,工人用 螺絲刀來修理東西,在這個類,我們發現是很難做的。因為我們Worker類別依賴一個具體的實作類別Hammer。所以我們用到面向介面程式的思想,改成如下的程式碼:
public interface Tools {
public String function();
# }
# 然後我們的Worker是透過這個介面來於其他細節類別進行依賴。程式碼如下:
public class Worker {
public void fix(Tools tool){
System.out.println("工人" tool.function());
}
# public static void main(String[] args) {
# new Worker()。 fix(new Hammer());
# new Worker()。 fix(new Screwdriver());
}
# }
# 我們的Hammer類別與Screwdriver類別實作這個介面
public class Hammer implements Tools{
# public String function(){
# return "用鐵鎚修理東西";
# }
# }
# public class Screwdriver implements Tools{
@Override
# public String function() {
# return "用螺絲起子修理東西";
# }
# }
# 這樣,透過面向介面編程,我們的程式碼就有了很高的擴展性,降低了程式碼之間的耦合度,提高了系統的穩定性。
介面隔離原則
# 介面隔離原則的定義是
客戶端不應該依賴他不需要的介面
換一種說法就是類別間的依賴關係應該建立在最小的介面上。這樣說好像比較難懂。我們透過一個例子來說明。我們知道在Java中一個具體類別實作了一個接口,那必然就要實作接口中的所有方法。如果我們有一個類別A和類別B透過介面I來依賴,類別B是對類別A依賴的實現,這個介面I有5個方法。但是類別A與類別B只透過方法1,2,3依賴,然後類別C與類別D透過介面I來依賴,類別D是對類別C依賴的實作但是他們卻是透過方法1,4,5依賴。那麼是必在實作介面的時候,類別B就要有實作他不需要的方法4和方法5 而類D就要實現他不需要的方法2,和方法3。這簡直就是一個災難的設計。
所以我們需要對接口進行拆分,就是把接口分成滿足依賴關係的最小接口,類B與類D不需要去實現與他們無關接口方法。例如在這個例子中,我們可以把接口拆成3個,第一個是僅僅由方法1的接口,第二個接口是包含2,3方法的,第三個接口是包含4,5方法的。這樣,我們的設計就滿足了介面隔離原則。
以上這些設計思想用英文的第一個字母可以組成SOLID ,滿足這個5個原則的程序也被稱為滿足了SOLID準則。
迪米特原則
# 迪米特原則也被稱為最小知識原則,他的定義
一個物件應該對其他物件保持最小的了解。
因為類別與類別之間的關係越密切,耦合度越大,當一個類別改變時,對另一個類別的影響也越大,所以這也是我們提倡的軟體程式設計的總的原則:低耦合,高內聚。迪米特法則還有一個更簡單的定義
# 只與直接的朋友通信。首先來解釋什麼是直接的朋友:每個物件都會與其他物件有耦合關係,只要兩個物件之間有耦合關係,我們就說這兩個物件之間是朋友關係。耦合的方式很多,依賴、關聯、組合、聚合等。其中,我們稱出現成員變數、方法參數、方法回傳值中的類別為直接的朋友,而出現在局部變數中的類別則不是直接的朋友。也就是說,陌生的類別最好不要作為局部變數的形式出現在類別的內部。
這裡我們可以用一個現實生活中的例子來講解一下。例如我們需要一張CD,我們可能去音像店去問老闆有沒有我們需要的那張CD,老闆說現在沒有,等有的時候你們來拿就行了。在這裡我們不需要關心老闆是從哪裡,怎麼獲得的那張CD,我們只和老闆(直接朋友)溝通,至於老闆從他的朋友那里通過何種條件得到的CD,我們不關心,我們不和老闆的朋友(陌生人)進行通信,這就是迪米特的一個應用。說穿了,就是一種中介的方式。我們透過老闆這個中介來和真正提供CD的人發生聯繫。
以上是Java物件導向設計的六大原則是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!