一:設計模式簡介程序員
每個模式描述了一個在咱們周圍不斷重複發生的問題,以及該問題的解決方案的核心。 ---- Christopher Alexander算法
軟件設計領域設計模式: 設計模式描述了軟件設計過程當中某一類常見問題的解決方案。
面向對象的設計模式: 面向對象的設計模式描述了面向對象設計過程當中,特定場景下,類與相互通訊的對象之間常見的組織關係。編程
二: GOF 23種設計模式設計模式
歷史性著做 《設計模式 : 可複用面向對象軟件的基礎》一書中描述了23種經典面向對象設計模式,創立了模式在軟件設計中的地位。該書四位做者被人們並稱Gang of four (GOF),「四人組」,該書描述的23種經典的設計模式被人們稱爲GOF 23種設計模式。編程語言
因爲《設計模式 : 可複用面向對象軟件的基礎》一書肯定了設計模式的地位,人們一般所說的設計模式隱含地表示「面向對象設計模式」。但並不意味「設計模式」就等於「面向對象設計模式」,也不意味着GOF 23種模式就表示全部「面向對象設計模式」。除了「面向對象設計模式」外還有其餘的設計模式,除了GOF 23 種設計模式外還有更多的設計模式。ide
三:設計模式與面向對象學習
面向對象設計模式解決的是類與相互通訊的對象之間的組織關係,包括他們的角色,職責,協做方式幾個方面。
面向對象設計模式是「好的面向對象設計」,所謂「好的面向對象設計」是那些知足「應對變化,提升複用」的設計。設計
面向對象的設計模式描述的是軟件設計,所以它是獨立於編程語言的,但面向對象的設計模式最終實現仍然要用面向對象的編程語言來表達。面向對象設計模式
面向對象設計模式不像算法技巧,能夠照搬照用,它是創建在對「面向對象」純熟,深刻的理解的基礎上的經驗性認識。掌握面向對象設計模式的前提是首先掌握「面向對象」。對象
四:從編程語言直觀的瞭解面向對象
各類面向對象編程語言互相有別,但都能看到他們面向對象的三大機制,「封裝」,「繼承」,「多態」。
封裝:隱藏內部實現
繼承:複用現有代碼
多態:改寫對象行爲
使用面向對象的編程語言,能夠推進程序員以面向對象的思惟來思考軟件設計結構,從而強化面向對象的編程範式。
C#是一門支持面向對象編程的優秀語言,包括:各類級別的封裝支持:單實現繼承+多接口實現;抽象方法與虛方法重寫。
五:OOPL並不是面向對象的所有
一般面向對象的編程語言(OOPL)認識到的面向對象,並非面向對象的所有,甚至只是淺陋的面向對象。
OOPL的三大機制「封裝」,「繼承」,「多態」能夠表達面向對象的全部概念,但這三大機制自己並無刻畫出面向對象的核心精神。換言之,既能夠用這三大機制作出「好的面向對象設計」,也能夠用着三大機制作出「差的面向對象設計」。不是使用了面嚮對象語言就實現了面向對象的設計與開發。所以咱們不能依賴編程語言的面向對象機制,來掌握面向對象。
OOPL沒有回答面向對象的根本性問題——咱們爲何要使用面向對象?咱們應該怎樣使用三大機制來實現「好的面向對象」?咱們應該遵循什麼樣的面向對象原則 ?
任何一個嚴肅的面向對象的程序員,都須要系統地學習面向對象的知識,單純從編程語言上得到的面向對象知識,不可以勝任面向對象設計與開發。
六:示例
示例場景:
咱們須要設計一我的事系統,其中一個功能是對各類不一樣類型的員工,計算其當月工資——不一樣類型的員工,擁有不一樣的薪資計算制度。
結構化作法:
1.得到人事系統中全部可能的員工類型。
2.根據不一樣員工類型所對應的不一樣薪資制度,計算工資。
enum EmployeeType {
Engineer;
Sales;
Manager;
..........
}
//薪資計算
if(type==EmployeeType.Engineer)
{
.............
}
else if(type==EmployeeType.Sales)
{
.............
}
.............
面向對象設計作法:
1.根據不一樣員工類型設計不一樣的類,並使這些類繼承自一個Employee抽象類,其中有一個抽象方法GetSalary。
2.在各自不一樣的員工類中,根據本身的薪資制度,重寫(override)GetSalary方法。
abstract class Employee{
...
public abstract float GetSalary();
}
class Engineer:Employee{
...
public override float GetSalary(){
}
}
class Sales:Employee{
...
public override float GetSalary(){
}
}
//顯示薪資程序
Employee e =EmployeeFactory.GetEmployee(id);
MessageBox.show(e.GetSalary());
七:面向結構作法與面向對象作法對比
示例場景:
隨着公司業務規模拓展,出現了更多類型的員工,好比鐘點工,計件工。。。。。等等,這對人事管理系統提出了挑戰--原有的程序必須改變。
結構化作法:
幾乎全部涉及到員工類型的地方,都須要修改,代碼須要從新編譯,從新部署。
面向對象作法:
只須要添加新的類文件,定義新的員工類,繼承Employee類重寫GetSalary()方法,而後EmployeeFactory.GetEmployee方法中根據條件,產生新的員工類型就能夠了。其餘地方(顯示程序,原有員工類)不須要作任何改變。
總結: 面向對象的作法在應對需求變化的時候更爲靈活。
八:從新認識面向對象
從宏觀層面來看,面向對象的構建方式更能適應軟件變化,能將變化所帶來的影響減爲最小。
從微觀上層來看,面向對象的方式更強調各個類的「責任」,新增員工類型不會影響原來員工類型的實現代碼——這更符合真實的世界,也更能控制變化所影響的範圍,畢竟Enginner類不該該爲新增的「鐘點工」來買單。
對象是什麼?
從概念層面講,對象是某種擁有責任的抽象。
從規格層面講,對象是一系列能夠被其餘對象使用的公共接口。
從語言層面來看,對象封裝了代碼和數據。
九:從設計原則到設計模式
針對接口編程,而不是針對實現編程:客戶無需知道所使用對象的特定類型,只需知道對象擁有客戶所指望的接口。
優先使用對象組合,而不是類繼承:類繼承一般爲「白箱複用」,對象組合一般爲「黑箱複用」。繼承在某種程度上破壞了封裝性,子類父類耦合度高,而對象組合則只要求被組合的對象具備良好定義的接口,耦合度低。
封裝變化點:使用封裝來建立對象之間的分界層,讓設計者能夠在分界成的一側進行修改,而不會對另外一側產生不良影響,從而實現層次間的鬆耦合。
使用重構獲得模式:設計模式的應用不宜先入爲主,一上來就使用設計模式是對設計模式最大的誤用,沒有一步到位的設計模式。敏捷軟件開發實踐提倡的」Refactoring to patterns「 是目前公認的最好的使用設計模式的方法。
十:設計原則
單一職責原則(SRP):一個類應該僅有一個引發它變化的緣由。
開放封閉原則(OCP):類模塊應該是可擴展的,可是不可修改(對擴展開放,對更改封閉。)
Liskov 替換原則(LSP):子類必須可以替換它們的基類。
依賴倒置原則(DIP):高層模塊不該該依賴低層模塊,兩者都應該依賴於抽象。抽象不該該依賴於實現細節,實現細節應該依賴於抽象。
接口隔離原則(ISP):不該該強迫客戶程序依賴於它們不用的方法。