設計模式之設計原則(一)

簡介

設計模式分類:

設計模式之設計原則(一)

superma.me

六大原則:

設計模式之設計原則(一)

superma.me

設計模式(Design pattern)是一套被反覆使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。設計模式是軟件工程的基石,是架構師所必備的技能之一。而其精髓其實就是六大原則。

面向對象編程

活字印刷術之前每頁都要單獨刻一個板,只要一個字錯了,就要全部重刻。如果要修正下文章,加一個字,就會導致後面刻好的板全部重刻。可維護性、可擴展性、可複用性太差。

所以有了面向對象。哈哈哈

活字印刷:每個字是個單獨的對象。

1、可維護:要改,只改要修改的字。

2、可複用:每個字可以拿到不同的文章裡用。

3、可擴展:可自己加字

4、靈活性好:橫排豎排

思想: 通過 封裝、繼承、多態 把程序的耦合度降低,易於擴展和複用。

上面這個例子參考了大話設計模式,歡迎大家去讀原書。

六大原則

一、單一職責原則

定義:不要存在多於一個導致類變更的原因。通俗的說,即一個類只負責一項職責。

但是由於需求迭代、時間緊迫等原因,很多時候我們經常會違背這一原則。比如:

用一個類描述動物呼吸這個場景:

class Animal{
public void breathe(String animal){
System.out.println(animal+"呼吸空氣");
}
}
public class Client{
public static void main(String[] args){
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("羊");
}
}

程序上線後,發現 並不是所有的動物都呼吸空氣的,比如魚就是呼吸水的。修改時如果遵循單一職責原則,需要將Animal類細分為陸生動物類Terrestrial,水生動物Aquatic,代碼如下:

class Terrestrial{
public void breathe(String animal){
System.out.println(animal+"呼吸空氣");
}
}
class Aquatic{
public void breathe(String animal){
System.out.println(animal+"呼吸水");
}
}
public class Client{
public static void main(String[] args){
Terrestrial terrestrial = new Terrestrial();
terrestrial.breathe("牛");
terrestrial.breathe("羊");

Aquatic aquatic = new Aquatic();
aquatic.breathe("魚");
}
}

我們會發現如果這樣修改花銷是很大的,除了將原來的類分解之外,還需要修改客戶端。而直接修改類Animal來達成目的雖然違背了單一職責原則,但花銷卻小的多,代碼如下:

class Animal{
public void breathe(String animal){
if("魚".equals(animal)){
System.out.println(animal+"呼吸水");
}else{
System.out.println(animal+"呼吸空氣");
}
}
}
public class Client{
public static void main(String[] args){
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("羊");
animal.breathe("魚");

}
}

但是這樣存在著隱患:有一天需要將魚分為呼吸淡水的魚和呼吸海水的魚,則又需要修改Animal類的breathe方法,而對原有代碼的修改會對調用“牛”“羊”等相關功能帶來風險,也許某一天你會發現程序運行的結果變為“牛呼吸水”了。這種修改方式直接在代碼級別上違背了單一職責原則,雖然修改起來最簡單,但隱患卻是最大的。還有一種修改方式:

class Animal{
public void breathe(String animal){
System.out.println(animal+"呼吸空氣");
}
public void breathe2(String animal){
System.out.println(animal+"呼吸水");
}
}
public class Client{
public static void main(String[] args){
Animal animal = new Animal();
animal.breathe("牛");
animal.breathe("羊");
animal.breathe2("魚");
}
}

這種修改方式沒有改動原來的方法,而是在類中新加了一個方法,這樣雖然也違背了單一職責原則,但在方法級別上卻是符合單一職責原則的,因為它並沒有動原來方法的代碼。

那麼在實際編程中,需要根據實際情況來確定。我的原則是:只有邏輯足夠簡單,才可以在代碼級別上違反單一職責原則;只有類中方法數量足夠少,才可以在方法級別上違反單一職責原則;

例如本文所舉的這個例子,它太簡單了,它只有一個方法,所以,無論是在代碼級別上違反單一職責原則,還是在方法級別上違反,都不會造成太大的影響。實際應用中的類都要複雜的多,一旦發生職責擴散而需要修改類時,除非這個類本身非常簡單,否則還是遵循單一職責原則的好。

遵循單一職責原的優點有:

  • 可以降低類的複雜度,一個類只負責一項職責,其邏輯肯定要比負責多項職責簡單的多;
  • 提高類的可讀性,提高系統的可維護性;
  • 變更引起的風險降低,變更是必然的,如果單一職責原則遵守的好,當修改一個功能時,可以顯著降低對其他功能的影響。

需要說明的一點是單一職責原則不只是面向對象編程思想所特有的,只要是模塊化的程序設計,都適用單一職責原則。

其他5個設計原則後面會講。

設計模式之設計原則(一)


分享到:


相關文章: