簡單工廠模式描述的是,通過類的繼承關系,父類(工廠類)與子類(產品類),調用父類中的方法,實際干活兒的是子類中的方法;封裝需求的不確定性,做出通用的編程,下面以常用的計算器為例:
最容易想到的寫法是:
1 Console.WriteLine("請輸入操作數1:"); 2 double a = double.Parse(Console.ReadLine()); 3 Console.WriteLine("請輸入操作符:"); 4 string opt = Console.ReadLine(); 5 Console.WriteLine("請輸入操作數2:"); 6 double b = double.Parse(Console.ReadLine()); 7 8 double result = 0; 9 10 switch (opt) 11 { 12 case "+": 13 result = a + b; 14 break; 15 case "-": 16 result = a - b; 17 break; 18 case "*": 19 result = a * b; 20 break; 21 case "/": 22 if (b == 0) 23 { 24 throw new Exception("被除數不能為0"); 25 } 26 result = a / b; 27 break; 28 } 29 Console.WriteLine("計算結果是:"+result);
這么寫,對于控制臺來說基本夠用了,但是它有很多的弊病:
1.計算結果是直接輸出到控制臺,如果要做一個WinForm版呢?(目前只有重新寫一遍,不能夠重用)
2.這里的case只考慮了基本的四則運算,業務變更后,如果有求平方、求立方、開方等運算呢?(那么只能去改寫好的方法,一個項目中只有一處還好說,如果有多處要修改,那就麻煩了,可擴展性太差)
3.這段代碼也沒有體現面向對象的3大特性:封裝、繼承、多態。
基于以上的種種弊端,需要修改代碼:
首先定義一個父類Operat,在類中不考慮未來是否有四則運算及怎樣運算
Operat類
1 /// <summary> 2 /// 父類計算方法 3 /// </summary> 4 public class Operat 5 { 6 public double NumberA { get; set; } 7 public double NumberB { get; set; } 8 /// <summary> 9 /// 構造函數 10 /// </summary> 11 /// <param name="a"></param> 12 /// <param name="b"></param> 13 public Operat(double a,double b) 14 { 15 this.NumberA = a; 16 this.NumberB = b; 17 } 18 19 public virtual double Oper() 20 { 21 double result = 0; 22 return result; 23 } 24 }
只定義了2個操作數和一個計算方法(虛方法,因為這里不知道未來有幾個運算)
再定義一個加法類(OperatAdd)來繼承它,并實現父類中的計算方法:
OperatAdd類(加法)
1 class OperatAdd : Operat 2 { 3 //構造函數 4 public OperatAdd(double a,double b):base(a,b) 5 { 6 7 } 8 /// <summary> 9 /// 子類重寫父類的Oper方法(實現) 10 /// </summary> 11 /// <returns></returns> 12 public override double Oper() 13 { 14 double result = 0; 15 result = NumberA + NumberB; 16 return result; 17 } 18 }
依次定義后面的3個類(減、乘、除)
OperatSub類(減法)
1 class OperatSub : Operat 2 { 3 public OperatSub(double a,double b):base(a,b) 4 { 5 6 } 7 public override double Oper() 8 { 9 double result = 0; 10 result= NumberA - NumberB; 11 return result; 12 } 13 }
OperatMult類(乘法)
1 class OperatMult:Operat 2 { 3 public OperatMult(double a,double b):base(a,b) 4 { 5 6 } 7 public override double Oper() 8 { 9 double result = 0; 10 result= NumberA * NumberB; 11 return result; 12 } 13 }
OperatVision類(除法)
1 class OperatVision:Operat 2 { 3 public OperatVision(double a,double b):base(a,b) 4 { 5 6 } 7 public override double Oper() 8 { 9 double result = 0; 10 if (NumberB==0) 11 { 12 throw new Exception("被除數不能為0"); 13 } 14 result = NumberA / NumberB; 15 return result; 16 } 17 }
這時候,應該考慮的問題是,在業務中,怎樣調用這4個子類中的運算方法(簡單工廠)
定義一個工廠類,由工廠類根據具體業務去調用具體的子類(產品類)
1 /// <summary> 2 /// 工廠類 3 /// </summary> 4 public class OperatFactory 5 { 6 public Operat JiSuan(double a, string opt, double b) 7 { 8 Operat opt1 = null; 9 //封裝了異同業務需求的差異 10 switch (opt) 11 { 12 case "+": 13 opt1 = new OperatAdd(a, b); //產品1(加法) 14 break; 15 case "-": 16 opt1 = new OperatSub(a, b); //產品2(減法) 17 break; 18 case "*": 19 opt1 = new OperatMult(a, b); //產品3(乘法) 20 break; 21 case "/": 22 opt1 = new OperatVision(a, b); //產品4(除法) 23 break; 24 } 25 return opt1; //返回父類對象 26 } 27 }
給opt賦不同的運算,工廠類就會去調用相應的子類,執行計算方法,new出相應的產品類,因為子類中都只是?return result;沒有考慮這個結果具體顯示在那個地方(控制臺還是winform中的label),就變得相當靈活了,并返回父類對象。
控制臺去使用時,調用工廠類中JiSuan()方法返回父類對象,即可:
1 Console.WriteLine("請輸入操作數1:"); 2 double a = double.Parse(Console.ReadLine()); 3 Console.WriteLine("請輸入操作符:"); 4 string opt = Console.ReadLine(); 5 Console.WriteLine("請輸入操作數2:"); 6 double b = double.Parse(Console.ReadLine()); 7 8 OperatFactory factory = new OperatFactory(); 9 Operat opt1 = factory.JiSuan(a, opt, b); 10 Console.WriteLine("計算結果是:{0}", opt1.Oper()); 11 Console.ReadKey();
而winform的代碼也很類似:
1 lbResult.Text = ""; 2 3 lbResult.ForeColor = Color.Red; 4 lbResult.Font = new Font("宋體", 12); 5 double a = double.Parse(txtNumber1.Text.Trim()); 6 string opt = cmbOperat.SelectedItem.ToString(); 7 double b = double.Parse(txtNumber2.Text.Trim()); 8 9 OperatFactory factory = new OperatFactory(); 10 Operat oper = factory.JiSuan(a, opt, b); 11 lbResult.Text = oper.Oper().ToString();
可以看出上面2段代碼的第二段幾乎是一樣的,代碼就足夠通用了。
?
?
?