設計模式的第一課内容主要是介紹了什麼是設計模式
Gof23種設計模式:曆史性著作《設計模式:可複用面向對象軟體的基礎》一書中描述了23種經典面向對象設計模式,創立了模式在軟體設計中的地位。該書四位作者被人們并稱為Gang of Four (GoF),"四人組",該書描述的23種經典設計模式又被人們稱為Gof23 種設計模式。
Gof23種設計模式并不意味着它表示了所有的面向對象的設計模式。面向對象的設計模式也并不意味着代表所有的設計模式。Gof23種設計模式隻是設計模式的基礎。
面向對象的設計模式主要解決的是"類與互相通信的對象之間的組織關系,包括它們的角色、職責、協作方式幾個方面。面向對象設計模式的目的是應對變化,提高複用。面向對象的設計模式是與語言無關的。它可以通過各種面向對象的語言來實作如C++、C#、Java等。
我們在程式設計當中,都了解面向對象的語言的三大特性:封裝、繼承、多态。但是,僅僅通過面向對象的語言是不能夠完全了解面向對象的設計的。面向對象語言的三大特性是為了實作面向對象而存在的,可以說面向對象是一篇文章,而三大特性是文章的寫作技巧,這些寫作技巧是為了寫這篇文章而服務的。
那麼這裡有一個小示例,可以初步的了解面向對象設計。
public abstract class Employee
... {
public abstract int GetSalary();
}
public class Engineer : Employee
... {
public override int GetSalary()
...{
//.....
}
}
public class Sales : Employee
... {
public override int GetSalary()
...{
//....
}
}
這裡有一個Employee的抽象類,兩個繼承于Employee的派生類。GetSalary是一個抽象方法,這個方法的調用由派生類的類型決定。
我們現在還有一個工廠類
public class EmployeeFactory
... {
public Employee GetEmployee(string EmployeeID)
...{
Employee objEmp = null;
switch (EmployeeID)
... {
case "Enginner":
objEmp = new Engineer();
break;
case "Sales":
objEmp = new Sales();
break;
}
return objEmp;
}
}
我們可以在程式種直接可以調用這個工廠類,來得到一個Employee
static void Main()
... {
EmployeeFactory objFactory = new EmployeeFactory();
Employee objEmp = objFactory.GetEmployee("Sales");
int Salary = objEmp.GetSalary();
}
如果這時候,我們的Employee類型增加了一個Worker。那麼我們隻需要新增一個Worker類,并僅僅需要修改GetEmployee的内部實作,其他的我們可以不作任何修改。Engineer和Sales類也可以不用修改。那麼就達到了一個松耦合的目的。這裡我們GetEmployee的參數可以是别的類型,比如說枚舉,或整形等。
那麼我們從宏觀的層面看就是面向對象的建構方式更能适應軟體的變化,能将變化所帶來的影響減為最小。
從微觀的層面來看面向對象的方式更強調各個類的"責任",新增員工類型不會影響原來員工類型的實作代碼。實際上就是對原有代碼的擴充。
對象是什麼?
- 從概念層面講,對象是某種擁有責任的抽象。
- 從規格層面講,對象是一系列可以被其他對象使用的公共接口。
- 從語言實作層面來看,對象封裝了代碼和資料。
面向對象的設計原則:
-
針對接口程式設計,而不是針對實作程式設計:客戶無需知道所使用對象的特定類型,隻需要知道對象擁有客戶所期望
的接口。
-
優先使用對象組合,而不是類繼承:類繼承通常為"白箱複用",對象組合通常為"黑箱複用"。繼承在某種程度
上破壞了封裝性,子類父類耦合度高;而對象組合則隻要求被組合的對象具有良好定義的接口,耦合度低。
- 封裝變化點:使用封裝來建立對象之間的分界層,讓設計者可以在分界層的一側進行修改,而不會對另一側産生不良的影響,進而實作層次間的松耦合。
- 使用重構得到模式:設計模式的應用不宜先入為主,一上來就使用設計模式是對設計模式的最大誤用。沒有一步到位的設計模式。提倡Refactoringto Patterns
- 單一職責原則:一個類應該僅有一個引起它變化的原因。
- 開放封閉原則:類子產品應該是可擴充的,但是不可修改(對擴充開放,對更改封閉)
- Liskov 替換原則:子類必須能夠替換它們的基類
- 依賴倒置原則:高層子產品不應該依賴于低層子產品,二者都應該依賴于抽象。 抽象不應該依賴于實作細節,實作細節應該依賴于抽象。
- 接口隔離原則:不應該強迫客戶程式依賴于它們不用的方法。