設計模式之禪
在繼續(xù)看后面的設計模式大pk之前,我需要對前面的知識進行梳理,對比以及形成自己的一套說辭
先來整理一下設計模式的首要的幾個原則。一共 六大
一、單一職責原則
一句很牛?哄哄的英文是這樣說的 "There should never be more than one reason for a class to change"
有且僅有一個原因引起類的變更。(這里用到的數(shù)學引語也是很偉大,有且僅有!有且僅有,就是只有唯一的一個原因可以引起變化)
舉個??吧!
現(xiàn)代人喜歡吃飯,睡覺,打豆豆。
class IEat{
virtual void eat() = 0;
};
class ISleep{
virtual void sleep() = 0;
};
class IDadd{
virtual void dadd() = 0;
};
三個接口分別實現(xiàn)吃飯睡覺打豆豆,每個行為都是只有一個變化引起,而且對外公布的是接口,而不是具體的實現(xiàn)類,所以因為具有單一原則,我們可以實現(xiàn)
- 讓類的復雜性降低,而不是讓一個類很牛逼。
- 讓可讀性提高,而不是天書一樣
- 可維護性提高,而不是沒有spanner,都不能修。
- 變更引起的風險低,變的是單一接口,所以,不會有連鎖反應。
人生有多少個十年,這個十年,就做一件事情。
所以,在寫程序的時候,多考慮一下,讓一個類或者一個方法只做一件事情。
二、里氏替換原則(我是一個有原則的類)
is-a。
定義:所有引用基類的地方必須能透明地使用其子類的對象。
爸爸在你就可以在,你在爸爸不可以在(特別是在做羞羞的事情的時候>_<!!!>);青出于藍而勝于藍,所以爸爸在的地方,你可以適應,你在的地方,爸爸未必適應。
里氏替換原則四層定義。
- 子類必須完全實現(xiàn)父類的方法。
- 子類可以有自己的個性。(仔大仔世界)
- 覆蓋或實現(xiàn)父類的方法時輸入?yún)?shù)可以被放大。
子類中的方法的前置條件必須與超類中被覆寫的方法的前置條件相同或者更寬松。
- 覆寫或實現(xiàn)父類的方法時輸出結果可以被縮小。
其實里氏替換原則就是為了增強程序的健壯性的,傳遞不同的子類實現(xiàn)不同的方法。
所以重載的時候,應該讓子類的參數(shù)更加寬松。
一言斃之日:撲朔迷離!
三、依賴倒置原則
高層模塊不應該依賴低層模塊,兩者都應該依賴其抽象。
抽象不應該依賴細節(jié)
細節(jié)應該依賴抽象
就是面向接口編程,不要面向細節(jié),不面向業(yè)務。
實現(xiàn)類之間不要產(chǎn)生什么直接依賴關系,通過接口或抽象類產(chǎn)生。
接口或抽象類不依賴實現(xiàn)類。
實現(xiàn)類依賴接口或抽象類。
?? 就是面向對象,面向接口編程!
提高代碼的可讀性和可維護性。減少類之間的耦合性,提高系統(tǒng)的穩(wěn)定性,降低并行開發(fā)引起的風險,提高代碼的可讀性和可維護性。
class IDriver{
void drive(ICar car);
};
class Driver:private IDriver{ // 實現(xiàn)這個方法為主
void drive(Icar car);
};
class ICar{
void run();
};
class Benz:private ICar{
void run();
};
class BWM:private Icar{
void run();
};
int main(){
IDriver driver = new Driver();
Icar benz = new Benz();
driver.drive(benz); // 傳入不同的參數(shù),顯式不同的輸出
}
測試的時候,直接新建一個接口,就可以測試!簡直無敵。
依賴的寫法
- 構造函數(shù)傳遞依賴對象
這個叫構造函數(shù)注入。這個不用多講,就是構造函數(shù)傳參傳入。
- setter方法傳遞依賴對象
class IDriver{
void setCar(Icar car);
};
class Driver:private IDriver{
private ICar iicar;
void setCar(Icar icar){
this.iicar = icar;
}
};
- 接口聲明依賴對象
此上的第二個??就是接口聲明依賴對象。
其實依賴倒置,就是通過抽象或接口使各個類或模塊的實現(xiàn)彼此獨立,不相互影響,實現(xiàn)模塊間的松耦合。
有五個原則需要在項目中守約(守約,今天的長城也很.....)
- 每個類盡量都有接口或抽象類,或者抽象類和接口兩者具備
- 變量的表面類型盡量是接口或者抽象類。
- 任何類都不應該從具體類派生(派生抽象類吧)
- 盡量不要覆寫基類的方法。
- 結合里氏替換原則使用 is-a
四、接口隔離原則(客戶端不應該依賴它不需要的接口&類間的依賴關系應該建立在最小的接口上)
建立單一的接口,不要建立臃腫龐大的接口。
接口盡量細化,同時接口中的方法盡量少。
不要和上面的單一混淆了!單一職責就是職責單一,職責!接口隔離原則,就是你的接口方法盡量少。
麻雀雖小,五臟俱全 定義的接口盡量比較小,但是也要涵蓋具體的業(yè)務。所以,接口小也要滿足單一職責的原則。
- 一般來說,接口一個只服務于一個子模塊或業(yè)務邏輯
- 通過業(yè)務邏輯壓縮public方法,自己內部使用private就好,這樣也能實現(xiàn)高內聚(犀利)
- 了解環(huán)境,不要盲從。不是叫你小,你就一定小,接口拆分的標準要按你的業(yè)務邏輯來。
五、迪米特法則(最少知識原則) 保持神秘感,知道太多,會惹來殺身之禍的??!
一個對象應該對其他對象有最少的了解。
一個類應該對自己需要耦合或調用的類知道得最少,你內在跟我沒關系,我只需要知道你提供的接口就可以了。
Only talk to your immediate friends
六、開閉原則(對修改關閉,對擴展開放)
盡量擴展以實現(xiàn)變化,而不是修改實現(xiàn)。
class IBook{
};
class NoteBook:public IBook{
};
class OffNoteBook:public NoteBook{
};// 只需要擴展 就可以實現(xiàn)不同的變化
對象約束
對于抽象要有約束,盡量不能修改,只是擴展,然后讓后面的類繼續(xù)繼承,然后擴展。
- 通過接口或抽象類約束擴展,對擴展進行邊界限定,不允許出現(xiàn)在接口或抽象類中不存在的public方法
- 參數(shù)類型、引用對象盡量使用接口或抽象類,而不是實現(xiàn)類
- 讓抽象層保持穩(wěn)定,一旦確定即不允許修改
list<IBook> lisBook; // 使用抽象類
元數(shù)據(jù)控制模塊行為
使用數(shù)據(jù),就是類似,配置文件,一旦確定基本不用修改。
制定項目章程
約定優(yōu)于配置
封裝變化
- 將相同的變化封裝到一個接口或抽象類中
- 將不同的變化封裝到不同的接口或抽象類中,不應該有兩個不同的變化出翔在同一個接口或抽象類中。
封裝可能的變化,具體可以繼續(xù)查看后面的23個設計模式,怎樣封裝變化。
六大原則結合起來SOLLID(solid 穩(wěn)定)很穩(wěn)。
擁抱變化,讓這六大原則伴隨23個設計模式,繼續(xù)乘風破浪,直掛云帆。(真有文化!)