學無止境,精益求精html
十年河東,十年河西,莫欺少年窮設計模式
學歷表明你的過去,能力表明你的如今,學習表明你的未來ide
大話設計模式一書中第一個開講的設計模式是簡單工廠模式,關於簡單工廠模式你們可參考鄙人的博客:代碼無錯就是優?簡單工廠模式 C#學習
固然,本篇博客所講的工廠模式和簡單工廠模式仍是很是相似的,所以,在進行工廠模式講解以前,咱們有必要重溫下簡單工廠模式優化
何爲工廠模式?不管是簡單工廠模式仍是本篇的工廠模式,其工廠類主要負責生產對象,而後經過相應的對象調用相關的方法this
在重溫簡單工廠模式以前,咱們再次看下簡單工廠模式的UML類圖spa
針對上述的簡單工廠模式UML類圖,咱們獲得以下敘述:設計
一、簡單工廠類是和運算類是有關聯的(實線加箭頭表明關聯),簡單工廠類的主要功能是生產運算對象code
二、運算類用斜體表示,說明運算類爲抽象類,運算類有兩個屬性及一個返回值爲 double 的方法htm
三、加減乘除類繼承運算類並實現GetResult()方法。
針對上述三點敘述,咱們可用以下代碼來實現(若是你還看不懂UML類圖,能夠參考鄙人博客:UML類圖應該怎麼看?)
public class 簡單工廠類 { double NumberA, NumberB; public 簡單工廠類() { } public 簡單工廠類(double A, double B) { this.NumberA = A; this.NumberB = B; } double Oper = new double(); public double Operate(string 符號) { switch (符號) { case "+": Oper = new 加法類().GetResult(NumberA, NumberB); break; case "-": Oper = new 減法類().GetResult(NumberA, NumberB); break; case "*": Oper = new 乘法類().GetResult(NumberA, NumberB); break; case "/": Oper = new 除法類().GetResult(NumberA, NumberB); break; } return Oper; } } public abstract class 運算類 { public abstract double GetResult(double NumberA, double NumberB); } public class 加法類:運算類 { public override double GetResult(double NumberA, double NumberB) { return NumberA + NumberB; } } public class 減法類 : 運算類 { public override double GetResult(double NumberA, double NumberB) { return NumberA - NumberB; } } public class 乘法類 : 運算類 { public override double GetResult(double NumberA, double NumberB) { return NumberA * NumberB; } } public class 除法類 : 運算類 { public override double GetResult(double NumberA, double NumberB) { if (NumberB != 0) return NumberA / NumberB; else throw new Exception("被除數不能爲零"); } }
static void Main(string[] args) { double A = 1; double B = 2; string F = "/"; 簡單工廠類 M = new 簡單工廠類(A,B); double Result = M.Operate(F); Console.WriteLine(Result); Console.ReadKey(); }
上述代碼是鄙人看着UML類圖本身設計的,和博客:代碼無錯就是優?簡單工廠模式 C# 中的設計代碼並不同!固然,這兩種代碼都準確的表達的簡單工廠的理念。有興趣的也能夠看下 代碼無錯就是優?簡單工廠模式 中的代碼實現形式。
OK,上述就是簡單工廠模式的代碼設計方案!
可是簡單工廠模式違反了設計模式的開閉原則,因此咱們有必要對其進一步優化!
所謂開閉原則:
這個原則其實有兩個特性,一個是說對於擴展是開放的,另外一個是說,對於修改是封閉的(ASD原則)
如何優化呢?
工廠模式閃亮登場...
首先看下工廠模式關於加減乘除的UML類圖
額,彷佛複雜了不少!
不急,咱們慢慢分析,而後再用代碼實現!
一、運算工廠接口依賴運算類,加法工廠類依賴加法類,減法工廠類依賴減法類,乘法工廠類依賴乘法類,除法工廠類依賴除法類!(虛線加箭頭表明依賴)
二、加減乘除工廠類繼承運算工廠接口,加減成熟類繼承運算類(三角加實線表明繼承)
三、下方的M的N次方類和對應的工廠類是用來擴展的。
那麼,分析了UML類圖的信息,怎樣用代碼實現呢?
首先咱們來建立左側部分的五個類(運算類及加減乘除類),以下:
/// <summary> /// 運算類 /// </summary> public class Operation { public double NumberA, NumberB; public virtual double GetResult() { return 0; } } public class Add : Operation { public override double GetResult() { return NumberA + NumberB; } } public class Sub : Operation { public override double GetResult() { return NumberA - NumberB; } } public class Mul : Operation { public override double GetResult() { return NumberA * NumberB; } } public class Div : Operation { public override double GetResult() { if (NumberB == 0) throw new Exception("被除數不能爲零"); return NumberA / NumberB; } }
其次,咱們來構建右側部分的一個接口及四個類(加減乘除工廠類),以下:
public interface IFactory { Operation GetOperation(); } public class AddFactory : IFactory { public Operation GetOperation() { return new Add(); } } public class SubFactory : IFactory { public Operation GetOperation() { return new Sub(); } } public class MulFactory : IFactory { public Operation GetOperation() { return new Mul(); } } public class DivFactory : IFactory { public Operation GetOperation() { return new Div(); } }
客戶端代碼爲:
static void Main(string[] args) { IFactory F = new AddFactory(); Operation AM = F.GetOperation(); AM.NumberA = 8; AM.NumberB = 7; double sum = AM.GetResult(); Console.WriteLine(sum); Console.ReadKey(); }
最後,咱們來運行一下(7+8=15):
寫到這兒,我能夠自豪的說:若是你要加平方根運算,我只需新增平方根類及平方根工廠。所以,如今的設計是不違反設計模式的開閉規則的!
咱們知道,在簡單工廠模式中,咱們能夠經過運工廠類的 Switch Case 來判斷具體的運算類型,可是上述所寫的工廠模式卻作不到了!這樣寫無形中加劇了客戶端的負擔(客戶端必須本身來判斷運算類型),所以:有沒有好的辦法解決這個弊端呢?
答案是有,並且還有一個有趣的名字,叫:雷鋒工廠
如何用代碼實現呢?
@陳臥龍的博客