設計模式的六大原則
一、設計模式的概念及作用
設計模式(Design pattern)是一套被反復使用、多數人知曉的、經過分類編目的、代碼設計經驗的總結。使用設計模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性。設計模式使代碼編制真正工程化,設計模式是軟件工程的基石,如同大廈的一塊塊磚石一樣。
二、六大原則
1.單一職責原則(Single Responsibility Principle,簡稱SRP)
1) 概念:一個類只負責一項職責。
2) 舉例說明:假設有一個接口,如下:
1 // 用戶接口 2 public interface IUser{ 3 //連接數據庫方法 4 public Connection getConnection(); 5 // 查詢用戶 6 public User qryUser(User user); 7 // 增加用戶 8 public int addUser(User user); 9 }
當操作數據庫的信息改變的時候,需要修改大量的代碼,所以,可以將操作數據庫的方法抽離出來,將上面的用戶接口改為:
1 // 數據庫操作類 2 public class DBUtil{ 3 // 連接數據庫方法4 public static Connection getConnection(){....} 5 } 6 7 // 用戶接口 8 public interface IUser{ 9 // 查詢用戶 10 public User qryUser(User user); 11 // 增加用戶 12 public int addUser(User user); 13 } 14 15 // 用戶實現類 16 public class UserImpl{17 Connection connection = null; 18 // 查詢用戶 19 public User qryUser(User user){ 20 connection = DBUtil.getConnection(); 21 .... 22 } 23 // 增加用戶 24 public int addUser(User user){ 25 connection = DBUtil.getConnection(); 26 .... 27 } 28 }
即,用戶接口中只操作用戶的基本信息,不操作數據庫。若要需要使用數據庫操作,將數據庫操作抽離出來,降低代碼的耦合性。
3) 優點:類的復雜度降低、可讀性提高、可維護性提高、擴展性提高、降低了變更引起的風險。
2.裏氏替換原則(Liskov Substitution Principle,簡稱LSP)
之所以叫裏氏替換原則1988年,是因為該原則是由麻省理工學院的一位姓裏的女士(Barbara Liskov)提出來的。
1) 概念:所有引用父類的地方必須能 透明使用子類,反過來 不成立。
2) 舉例說明:
喜歡動物 = 喜歡狗,因為動物中 包含狗,等式是成立的。
喜歡狗 != 喜歡動物。
class Animal{}
class Dog extends Animal{}
3) 優點:增強程序的健壯性,即使增加了子類,原有的子類還可以繼續運行。
3.依賴倒置原則(Dependence Inversion Principle,簡稱DIP)
1) 概念:依賴倒置原則的本質就是通過抽象(接口或抽象類)使個各類或模塊的實現彼此獨立,互不影響,實現模塊間的松耦合。
2)舉例說明:假設有一個CD唱片,CD唱片的播放 需要 CD播放機,即:
1 // CD 2 class CDRom{ 3 public void play(){ 4 System.out.println("play CDRom"); 5 } 6 } 7 8 // CD播放機 9 class Player{ 10 public void start(CDRom cd){ 11 System.out.println("CD playing ..."); 12 cd.play(); 13 } 14 } 15 16 // 測試方法 17 public class Main{ 18 public static void main(Stirng[] args){ 19 Player player = new Player(); 20 CDRom cd = new CDRom(); 21 player.start(cd); 22 } 23 }
隨著科技的發達,DVD出現了,這時候就需要DVD播放機了,如下:
1 // DVD 2 class DVDRom{ 3 public void play(){ 4 System.out.println("play DVDRom"); 5 } 6 } 7 8 // DVD播放器 9 class Player{ 10 public void start(CDRom cd){ 11 System.out.println("DVD playing ..."); 12 cd.play(); 13 } 14 }
又隨著科技的發達,MP3、MP4等問世,這時候我們又需要定義更多的類,這樣子會很繁瑣,所以,可以定義一個上層接口,讓下層的類去實現,將上面的代碼 改為 如下:
1 // 媒體接口 2 inteferce Media{ // cd,dvd,mp3,mp4.mp5... 3 public void play(); 4 } 5 6 // DVD,並實現媒體接口 7 class DVDRom impl Media{ 8 public void play(){ 9 System.out.println("play DVDRom"); 10 } 11 } 12 13 // CD,並實現媒體接口 14 class CDRom impl Media{ 15 public void play(){ 16 System.out.println("play CDRom"); 17 } 18 } 19 20 // 通用播放機 21 class Player{ 22 public void start(Media media){ 23 System.out.println("playing ..."); 24 media.play(); 25 } 26 } 27 28 // 測試方法 29 public class Main{ 30 public static void main(Stirng[] args){ 31 Player player = new Player(); 32 media cd = new CDRom(); 33 34 media dvd = new DVDRom(); 35 player.start(dvd); 36 } 37 }
3) 優點:在小型項目中很難體現出來。但在大中型項目中可以減少需求變化引起的工作量,使並行開發更友好。
4.接口隔離原則(Interface Segregation Principle,簡稱ISP)
1.概念:類間的依賴關系應該建立在最小的接口上。
可以理解為:建立單一接口,不要建立龐大臃腫的接口,盡量細化接口,接口中的方法盡量少。也就是說,我們要為各個類建立專用的接口,而不要試圖去建立一個很龐大的接口供所有依賴它的類去調用。
一句話概括:一個接口中不要什麽事情都去做,其實什麽事情都做不好。
2.舉例說明:
1 // 燈接口 2 interface light{ 3 // 開燈方法 4 on(); 5 // 關燈方法 6 off(); 7 // 維修方法 8 repare(); 9 // 開電視方法 10 turnOnTV(); 11 }
上面的燈接口中,既有燈的方法,又有工作人員的接口,又有電視的接口,這樣 一個接口就會顯得很臃腫,很龐大。
運用接口隔離原則之後,將接口細化,分散為多個接口,可以預防外來變更的擴散。如下:
1 // 燈接口 2 interface light{ 3 // 開燈方法 4 on(); 5 // 關燈方法 6 off(); 7 } 8 9 // 電視接口 10 intefece tv{ 11 // 開電視接口 12 on(); 13 // 關電視接口 14 off(); 15 } 16 17 // 工作人員 18 intefece worker{ 19 // 維修 20 repaire(); 21 }
3.優點:通過分散定義多個接口,可以預防外來變更的擴散,提高系統的靈活性和可維護性。
5.迪米特法則(Law of Demeter,簡稱LoD)
1.概念:類間解耦。
2.問題由來:類與類之間的關系越密切,耦合度越大,當一個類發生改變時,對另一個類的影響也越大。
3.註意點:迪米特法則的初衷是降低類之間的耦合,由於每個類都減少了不必要的依賴,因此的確可以降低耦合關系。但是凡事都有度,雖然可以避免與非直接的類通信,但是要通信,必然會通過一個“中介”來發生聯系。過分的使用迪米特原則,會產生大量這樣的中介和傳遞類,導致系統復雜度變大。所以在采用迪米特法則時要反復權衡,既做到結構清晰,又要高內聚低耦合。
6.開閉原則(Open Close Principle,簡稱OCP)
1). 思想:盡量通過擴展軟件實體來解決需求變化,而不是通過修改已有的代碼來完成變化。
2). 開:對擴展開放
關:對修改關閉
總結:單一職責原則告訴我們實現類要職責單一;
裏氏替換原則告訴我們不要破壞繼承體系;
依賴倒置原則告訴我們要面向接口編程;
接口隔離原則告訴我們在設計接口的時候要精簡單一;
迪米特法則告訴我們要降低耦合;
開閉原則是總綱,他告訴我們要對擴展開放,對修改關閉。
設計模式的六大原則