前言: "軟體模式的偉大之處, 就在於他們傳達了許多有用的設計思想. 所以, 在學習了大量模式之後, 就理應成為非常優秀的軟體設計人員, 不是嗎? 當學習、使用了幾十個設計模式之後, 我也曾這樣認為. 模式幫助我開發靈活的框架, 幫助我構建堅固、可擴展的軟體系統. 但是幾年之後, 我卻發現自己在模式 ...
前言:
"軟體模式的偉大之處, 就在於他們傳達了許多有用的設計思想. 所以, 在學習了大量模式之後, 就理應成為非常優秀的軟體設計人員, 不是嗎? 當學習、使用了幾十個設計模式之後, 我也曾這樣認為. 模式幫助我開發靈活的框架, 幫助我構建堅固、可擴展的軟體系統. 但是幾年之後, 我卻發現自己在模式方面的知識和使用模式的方式總是使我在工作中犯過度設計的錯誤.
設計技術進一步提高之後, 我發現自己使用模式的方式逐漸發生了變化: 我開始 '通過重構實現模式、趨向模式和去除模式(refactoring to, towards, and away from pattern)', 而不再是預先(up-front)設計中使用模式, 也不再過早地在代碼中加入模式. 這種使用模式的新方式來自於我對極限變成(xp)設計實踐的採用, 它幫助我即避免了過度設計, 又不至於設計不足. " -- 引自 Refactoring to Patterns, 當然是翻譯版
在我決定使用新方法學習設計模式之前, 我也看過不少設計模式的資料和書籍, 但大部分都是當時懂了, 不久之後, 再度遺忘, 仿佛沒學過一般(主要是在平時不用, 所以不忘我都不信了). 乾脆記錄下來, 以後就算不用, 只要有網路的地方, 還可以拿出來看看.
學習的順序, 就不按照類型去區分學習了, 看心情來選擇學習.
一、簡單工廠
首先, 我們有三件產品, 普通轎車,越野,跑車, 創建完之後, 會返回這三種產品中的一件, 但是我又不知道是哪一件, 怎麼辦呢, 同一個方法返回不同的幾種東西.
面向對象有一種很強大的特性, 多態. 首先要抽象他們, 提取出他們共同的部分, 比如, 相同的行為(啟動, 剎車, 加速, 行駛), 或者相同的特征(都屬於車, 都有輪子). 對於他們不同的部分, 可以放在各自的類中. 此處就是提取抽象, 隔離變化的思想.
那按照這種思想, 先分析他們相同的部分, 然後提取出來, 形成一個基類.
public enum EnumCar { SUV, Normal, Sports } /// <summary> /// 抽象基類, 也可以做成介面, 或者就是一個普通類, 主要是為了實現多態 /// </summary> public abstract class Car { /// <summary> /// 車名 /// </summary> public string Name { get; set; } /// <summary> /// 車型 /// </summary> public string CarType { get; set; } /// <summary> /// 汽車品牌 /// </summary> public string Brand { get; set; } /// <summary> /// 啟動汽車 /// </summary> public virtual void Start() { Console.WriteLine(this.Name + " Start "); } }
接下來, 可以建各自的類了.
public class Normal : Car { public Normal() { this.CarType = "普通轎車"; } public override void Start() { Console.WriteLine(this.CarType); base.Start(); } } public class Sports : Car { public Sports() { this.CarType = "跑車"; } public override void Start() { Console.WriteLine(this.CarType); base.Start(); } } public class SUV : Car { public SUV() { this.CarType = "越野"; } public override void Start() { Console.WriteLine(this.CarType); base.Start(); } }
做好這些之後, 就可以開始 簡單工廠的部分了. 那建工廠之前, 還是要明確一下, 這個工廠的職責, 通過傳入不同的類型, 來創建不同的產品. 相同的入參, 不同的返回值.
public class CarFactory { public static Car Create(EnumCar car) { switch (car) { case EnumCar.SUV: return new SUV(); case EnumCar.Normal: return new Normal(); case EnumCar.Sports: return new Sports(); default: return new Normal(); } } }
ok, 一切弄完之後, 就可以測試一下了:
static void Main(string[] args) { Car car = CarFactory.Create(EnumCar.SUV); car.Start(); Console.ReadKey(); }
結果如下:
二、類圖
三、自己的理解
所有的設計, 都是為了簡化應用. 無病呻吟, 實非目的, 所以就根據我在項目中的所見所聞所用, 列舉一下幾個使用場景.
1. 服務端可以通過獲取客戶端傳入的參數或者根據配置文件中配置的項, 來創建對應的類, 以此來執行不同的一套操作, 完成相同的工作, 當然, 結果可以是不一樣的.
對我映像比較深的一個項目實例, 就是配合項目配置文件(appsetting), 在策略模式中, 選擇創建哪一種緩存機制, 來達到選擇使用緩存的功能.
2. 可以改進抽象工廠. 具體在抽象工廠中介紹.
四、問題
從這個例子中, 能看到, 我能新建的產品, 是一定的, 或者說是死的, 如果我想新加一種產品, 在不改代碼的情況下, 是加不進去的. 怎麼加進去呢? 下一篇揭曉謎底.