背景:據說設計模式是進入BAT的必經之路。java
First、何謂設計模式:數據庫
設計模式(Design Pattern)是一套被反覆使用、多數人知曉的、通過分類的、代碼設計經驗的總結。設計模式
設計模式的好處&學習目的:微信
一、爲了代碼可重用行、讓代碼更易被他人理解、保證代碼的可靠性、使代碼編寫真正實現工程化;網絡
二、設計模式便於咱們維護項目,加強系統的健壯性和可擴展性;學習
三、設計模式還能夠鍛鍊碼農的設計思惟、昇華代碼質量等。spa
六大指導原則:設計
程序設計模式有六大基本指導原則,但規則畢竟都是人定的,So咱們要靈活遵照、靈活運用這六大原則。code
1、開-閉原則:blog
一、開閉原則顧名思義就是對修改關閉,對擴展開放;
二、開閉原則是六大原則的核心,即咱們以後作的任何改變都不須要修改原有的代碼,只須要加入一些新的實現便可達到目的;
三、開閉原則也是任何一個系統設計指望達到的理想境界。
2、單一職責原則:
單一職責即每一個類都只負責單一的功能,莫要太貪心,除此以外儘可能把一個類的功能完善到極致,能夠用final來修飾的程度。下面就有一個例子類Scientific 從一個文件中讀取兩個數,並返回二者之和,如此設計能夠很明顯的看到它們之間的職責問題存在太多耦合了。如圖:
上圖中顯示的Scientific 類並無錯,可是咱們要是讀取文件的地址改變了呢?要是結果改成二者之差、二者之積或二者之商或者是二者之模呢?而後,咱們須要複製許多份相同的代碼,想一想這種設計就不合理;這時咱們就要考慮下「單一職責原則」,分離出一個類ReadFile 來讀取數據,再分離出一個類DesignScientific 對讀取到的數據進行處理(加減乘除等)。
1 import java.io.BufferedReader; 2 import java.io.FileReader; 3 public class ReadFile { 4
5 private int numOne; 6 private int numTwo; 7
8 public ReadFile(String path) throws Exception { 9 BufferedReader br = new BufferedReader(new FileReader(path)); 10 numOne = Integer.valueOf(br.readLine()); 11 numTwo = Integer.valueOf(br.readLine()); 12 System.out.println("numOne is: "+numOne+" && "+"numTwo is: "+numTwo); 13 } 14
15 public int getNumOne() { 16 return numOne; 17 } 18
19 public int getnumTwo() { 20 return numTwo; 21 } 22 }
如此,將一個類拆爲兩個,既不會有那麼多重複的代碼,也多了跟多結果的選擇性,也偏偏體現了單一職責原則是咱們設計模式最應該遵照的原則之一。
3、里氏替換原則:
里氏替換原則具體指的是一個子類能夠在替換掉其父類後正常工做,也就是自類不該該重寫父類的方法,其主要做用是規範繼承是子類的一些書寫規則,主要目的是保持父類方法不被覆蓋。
一、子類能夠實現父類的抽象方法,但不能覆蓋父類的抽象方法(要不從新寫給類算了,幹嗎要繼承);
二、子類中能夠增長本身特有的方法;
三、當子類覆蓋或實現父類方法時,方法的前置條件(方法的形參)要比其父類方法的輸入參數更寬鬆(如:fun(ArrayLIst, list) VS fun(List, list) );
四、當子類的方法實現父類的抽象方法時,方法的後置條件(方法的返回值)要比其父類更嚴格。
4、接口隔離原則:
接口隔離原則也叫作接口最小化原則,指的是一個接口擁有的行爲應該儘量的最小。
一、若是設計的時候沒有考慮到接口隔離原則,就會出現一個類實現了一個接口但實現類中只有個別的方法實現了其餘方法都是空的情況,致使強制實現了不起不實現而又本不應實現的方法,而最終也一直沒有調用過此方法,形成資源浪費;
二、好比咱們設計一個手機Mobile的接口時,就要考慮手機哪些屬性時必須的,要讓該接口儘可能最小最細化,即只要是手機就必需要具有的屬性。
沒有遵照接口隔離原則的Mobile接口設計:
1 public interface Mobile {
2 public void call(); //手機能夠打電話
3 public void sendMessage(); //手機能夠發短信
4 public void weChat(); //手機能夠上微信weChat?
5 }
上述Mobile接口很明顯不是一個手機必須具有的功能屬性,那麼什麼的Mobile接口就不是最小接口,由於非智能手機就只能夠打電話和發短信,而上微信就是智能手機的專屬特性,如此就會有多餘的實現方法,能夠作以下修改,充分考慮接口隔離原則。
1 public interface SmartPhone extends Mobile{
2 public void weChat(); //智能手機的接口就能夠加入這個方法了
3 }
5、依賴倒置原則:
這個原則描述的是高層模塊不應依賴於低層模塊,兩個模塊都應該依賴依賴於抽象,抽象不該該依賴於細節,細節應該依賴於抽象。由於實現都是易變的,只有抽象是穩定的,因此當咱們依賴於抽象是,實現的變化就不會影響客戶端的調用;就好比上面「單一職責」中的計算器的例子,計算器實際上是依賴於數據讀取類的,這樣設計仍是有一些缺陷,由於如果當數據不是在文件裏,而是在數據庫當中呢?這時候爲了避免影響現有的代碼,只能將ReaderFile類整個大改,或是新增一個DBReader類,把程序代碼中全部使用到ReaderFile讀取到地方替換成DBReader,這樣作勉強能夠接受,可是仍然達不到可複製化的標準;如果數據讀取有的是從數據庫、有點是從XML文件、有的是從網絡或是從鍵盤輸入讀取,這時就有充分考慮依賴倒置原則。
1 public interface Reader {
2 //依賴倒置抽象出的一個抽象接口
3 public int getA(); 4 public int getB(); 5 }
依賴倒置原則讓咱們抽象出一個抽象類或者接口,來表述數據讀取行爲,而後讓上面全部的讀取方式所實現的類都實現該接口,客戶端方面只使用咱們定義好的接口,當咱們的實現變化時,咱們只需設置下不一樣的實際類型就OK了,這樣設計對於系統的擴展行將會是一個巨大的提高;這樣設計的話,計算器就依賴於一個很穩定的抽象接口,以後不管是從哪裏讀取數據,兩個獲取數據的方法都不會改變;不管是DBReader、XMLReader、NetReader或是OutPutStreamReader之類的均可以實現Reader這個抽象接口,不論是從哪裏讀取數據都OK,由於咱們不須要關心這個,只要能夠從Reader接口中得到A和B的值就OK了;同時,依賴於抽象也體現了JAVA語言的動態特性。
6、迪米特原則:
迪米特原則也稱最小知道原則,就是一個類儘可能不該該知道(包括)其餘類太多的東西,不要和其餘類有太多的交集。該原則的制定的終極目的就是解耦,即將細節所有高內聚於類的內部,其餘的類只需知道這個類主要提供的功能就OK了,減小沒必要要的依賴,高聚合低耦合。