好久沒有寫博客啦,因最近在忙於弄自己的一個網站,一直沒有時間寫了,在這裡跟廣大園友說聲抱歉,今天也正好是中秋節,在這裡祝大家節日快樂!廢話少說,接續上節的繼續寫下去。
依賴倒置原則(Dependence Inversion Principle),簡稱DIP:他的核心思想就是在進行業務設計時,高層模塊不應該依賴於底層模塊,兩者應該依賴與抽象,抽象而不依賴於具體實現,具體實現應該依賴與抽象,這樣會使代碼變得更穩定,從而大大提高了程序應對業務變化的能力。
我們來看一下一個例子來更深刻的理解一下上面的核心思想:
1 public class Car 2 3 { 4 5 public string CarName; 6 7 8 9 public Car(string carname) 10 11 { 12 13 this.CarName = carname; 14 15 } 16 17 public void 駕駛() 18 19 { 20 21 Console.WriteLine(CarName + ":駕駛"); 22 23 } 24 25 26 27 } 28 29 30 31 public class Person 32 33 { 34 35 public void drive() 36 37 { 38 39 Car bmw=new Car("BMW"); 40 41 bmw.駕駛(); 42 43 } 44 45 }
從上面的例子看一下能發現Person類依賴與Car類,這樣耦合度高,這樣的話比如說Car類發生變化時很容易出現問題,比如說哪天這個Person類不想開汽車了想開火車或者飛機時怎麼辦,那我們可以改造一下上面的類,Person類不依賴於Car這個具體實現,我們要依賴抽象,依賴與交通工具,我們看看代碼:
1 //交通工具才抽象 2 3 public interface IVehicle 4 5 { 6 7 void 駕駛(); 8 9 } 10 11 //汽車 12 13 public class Car : IVehicle 14 15 { 16 17 public string CarName; 18 19 20 21 public Car(string carname) 22 23 { 24 25 this.CarName = carname; 26 27 } 28 29 public void 駕駛() 30 31 { 32 33 Console.WriteLine(CarName + ":駕駛"); 34 35 } 36 37 38 39 } 40 41 //飛機 42 43 public class Plane : IVehicle 44 45 { 46 47 public string PlaneName; 48 49 50 51 public Plane(string carname) 52 53 { 54 55 this.PlaneName = carname; 56 57 } 58 59 public void 駕駛() 60 61 { 62 63 Console.WriteLine(PlaneName + ":駕駛"); 64 65 } 66 67 68 69 } 70 71 //火車 72 73 public class Train : IVehicle 74 75 { 76 77 public string TrainName; 78 79 80 81 public Train(string carname) 82 83 { 84 85 this.TrainName = carname; 86 87 } 88 89 public void 駕駛() 90 91 { 92 93 Console.WriteLine(TrainName + ":駕駛"); 94 95 } 96 97 98 99 } 100 101 public class Person 102 103 { 104 105 private IVehicle machine = null; 106 107 public Person(IVehicle _vehicle) 108 109 { 110 111 machine = _vehicle; 112 113 } 114 115 public void drive() 116 117 { 118 119 machine.駕駛(); 120 121 } 122 123 }
類圖如下:
客戶端調用代碼:
1 Person person1=new Person(new Car("寶馬")); 2 3 person1.drive(); 4 5 Person person2=new Person(new Plane("飛機")); 6 7 person2.drive(); 8 9 Person person3=new Person(new Train("火車")); 10 11 person3.drive(); 12 13 Console.ReadLine();
輸出結果如下:
從以上代碼可以看出Person類的駕駛方法來說不需要依賴具體的交通工具,只依賴抽象,具體的哪一個交通工具是從外部傳入的。這樣其實就是抽象編碼。也是依賴倒置的有點。
組合優於繼承:他的核心思想就是組合比繼承更大的靈活性和穩定結構。
為什麼怎麼說呢,我們來看看他們各自的優缺點:
繼承優點:
1)新的實現很容易,因為大部分是繼承而來的。
2)很容易修改和擴展已有的實現
繼承的缺點:
1)打破了封裝,因為基類想子類暴露額具體的實現細節。
2)白盒重用,因為基類的內部細節通常對子類是可見的。
3)當父類發生改變時子類也做出相應的改變。
4)不能在運行時修改由父類繼承來的實現。
組合優點:
1)被包含對象通過包含他們的類來訪問
2)黑盒重用,因為被包含對象的內部細節是不可見的
3)很好的封裝
4)每一個類都專注於一個任務
5)通過獲得和被包含對象的類型相同的對象引用,可以在運行時動態定義組合的方式
組合缺點:
1)系統可能會包含更過的對象
2)為了使組合時可以使用不同的對象,必須小心的定義接口。
近年來,大家都開始注意設計模式。那麼,到底我們為什麼要用設計模式呢?這麼多設計模式為什麼要這麼設計呢?說實話,以前我還真沒搞清楚。就是看大家一口一個"Design pattern",心就有點發虛。於是就買了本"四人幫"的設計模式,結果看得似懂非懂:看得時候好像是懂了,過一會就忘了。可能是本人比較"愚鈍"吧:))最近,有了點感悟。"獨樂不如眾樂",與大家分享一下,還望指教!
為什麼要提倡"Design Pattern"呢?根本原因是為了代碼復用,增加可維護性。那麼怎麼才能實現代碼復用呢?OO界有前輩的幾個原則:"開-閉"原則(Open Closed Principal)、裡氏代換原則、合成復用原則。設計模式就是實現了這些原則,從而達到了代碼復用、增加可維護性的目的。
一、"開-閉"原則
此原則是由"Bertrand Meyer"提出的。原文是:"Software entities should be open for extension,but closed for modification"。就是說模塊應對擴展開放,而對修改關閉。模塊應盡量在不修改原(是"原",指原來的代碼)代碼的情況下進行擴展。那麼怎麼擴展呢?我們看工廠模式"factory pattern":假設中關村有一個賣盜版盤和毛片的小子,我們給他設計一"光盤銷售管理軟件"。我們應該先設計一"光盤"接口。如圖:
而盜版盤和毛片是其子類。小子通過"DiscFactory"來管理這些光盤。代碼為:
public class DiscFactory{
public static 光盤 getDisc(String name){
return (光盤)Class.forName(name).getInstance();
}}
有人要買盜版盤,怎麼實現呢?
public class 小子{
public static void main(String[] args){
光盤 d=DiscFactory.getDisc("盜版盤");
光盤.賣();
}}
如果有一天,這小子良心發現了,開始賣正版軟件。沒關系,我們只要再創建一個"光盤"的子類"正版軟件"就可以了。不需要修改原結構和代碼。怎麼樣?對擴展開發,對修改關閉。"開-閉原則"
工廠模式是對具體產品進行擴展,有的項目可能需要更多的擴展性,要對這個"工廠"也進行擴展,那就成了"抽象工廠模式"。
二、裡氏代換原則
裡氏代換原則是由"Barbara Liskov"提出的。如果調用的是父類的話,那麼換成子類也完全可以運行。比如:
光盤 d=new 盜版盤();
d.賣();
現在要將"盜版盤"類改為"毛片"類,沒問題,完全可以運行。Java編譯程序會檢查程序是否符合裡氏代換原則。還記得java繼承的一個原則嗎?子類overload方法的訪問權限不能小於父類對應方法的訪問......余下全文>>
歲月沉澱出的流年,無論我怎樣努力都是荒蕪中的一段夢,過去了,再也回不去了。如果說;記憶能將午夜夢回的淚水撥動出幸福的旋律,我想;關於你的到來不管是想起還是淚水,都應該是我最幸福律動,曾聽人說,流浪者,必須要經過一條漂泊中的河橋,這座河橋不戀世俗名利,沒有太多的繁華,只是在左右孤單中寂寞的旅程,只要邁步走過,那便就是幸福的終點。