一、舉例 用控制台程式做一個非常簡單的電腦,實現加減乘除運算即可,那麼,大家自然而然的會寫出如下代碼 二、演繹 1、第一步演繹 ①由於在判斷運算符時,用的是if語句,這意味著每個條件都需要做判斷,相當於電腦做了三次無用功。 ②沒有輸入校驗,例如,除數不能為零的問題等等 就上述兩個問題,做如下修改 ...
一、舉例
用控制台程式做一個非常簡單的電腦,實現加減乘除運算即可,那麼,大家自然而然的會寫出如下代碼
1 static void Main(string[] args) 2 { 3 Console.WriteLine("請輸入數字A:"); 4 string strNumA = Console.ReadLine(); 5 Console.WriteLine("請選擇運算符號(+、-、*、、)"); 6 string strOperate = Console.ReadLine(); 7 Console.WriteLine("請輸入數字C:"); 8 string strNumB = Console.ReadLine(); 9 string strResult = ""; 10 if (strOperate == "+") 11 { 12 strResult = Convert.ToString(Convert.ToDouble(strNumA) + Convert.ToDouble(strNumB)); 13 } 14 if (strOperate == "-") 15 { 16 strResult = Convert.ToString(Convert.ToDouble(strNumA) - Convert.ToDouble(strNumB)); 17 } 18 if (strOperate == "*") 19 { 20 strResult = Convert.ToString(Convert.ToDouble(strNumA) * Convert.ToDouble(strNumB)); 21 } 22 if (strOperate == "/") 23 { 24 strResult = Convert.ToString(Convert.ToDouble(strNumA) / Convert.ToDouble(strNumB)); 25 } 26 Console.WriteLine($"結果是:{strResult}"); 27 Console.ReadKey(); 28 }
二、演繹
1、第一步演繹
①由於在判斷運算符時,用的是if語句,這意味著每個條件都需要做判斷,相當於電腦做了三次無用功。
②沒有輸入校驗,例如,除數不能為零的問題等等
就上述兩個問題,做如下修改:(輸入校驗此處先只做除數為零的校驗)
1 static void Main(string[] args) 2 { 3 Console.WriteLine("請輸入數字A:"); 4 string strNumA = Console.ReadLine(); 5 Console.WriteLine("請選擇運算符號(+、-、*、、)"); 6 string strOperate = Console.ReadLine(); 7 Console.WriteLine("請輸入數字C:"); 8 string strNumB = Console.ReadLine(); 9 string strResult = ""; 10 switch (strOperate) 11 { 12 case "+": 13 strResult = Convert.ToString(Convert.ToDouble(strNumA) + Convert.ToDouble(strNumB)); 14 break; 15 case "-": 16 strResult = Convert.ToString(Convert.ToDouble(strNumA) - Convert.ToDouble(strNumB)); 17 break; 18 case "*": 19 strResult = Convert.ToString(Convert.ToDouble(strNumA) * Convert.ToDouble(strNumB)); 20 break; 21 case "/": 22 if (strNumB != "0") 23 { 24 strResult = Convert.ToString(Convert.ToDouble(strNumA) / Convert.ToDouble(strNumB)); 25 } 26 else 27 { 28 strResult = "除數不能為0"; 29 } 30 break; 31 } 32 Console.WriteLine($"結果是:{strResult}"); 33 Console.ReadKey(); 34 }
2、第二步演繹
①上述寫的簡單的計算器僅僅體現了面向過程的編程,沒有體現面向對象的編程
②上述代碼使用控制台應用實現的,假如有一天我需要用Winform、Web 等實現一模一樣的需求,那麼,上述代碼則需要重新編寫,好可怕。
就上述問題,做如下修改:
將業務邏輯與界面分離
Operation運算類
1 public class Operation 2 { 3 public static double GetResult(double numA, double numB, string strOperate) 4 { 5 double result = 0d; 6 switch (strOperate) 7 { 8 case "+": 9 result = numA + numB; 10 break; 11 case "-": 12 result = numA - numB; 13 break; 14 case "*": 15 result = numA * numB; 16 break; 17 case "/": 18 result = numA / numB; 19 break; 20 } 21 return result; 22 } 23 }
客戶端
1 static void Main(string[] args) 2 { 3 try 4 { 5 Console.WriteLine("請輸入數字A:"); 6 string strNumA = Console.ReadLine(); 7 Console.WriteLine("請選擇運算符號(+、-、*、、)"); 8 string strOperate = Console.ReadLine(); 9 Console.WriteLine("請輸入數字C:"); 10 string strNumB = Console.ReadLine(); 11 string strResult = ""; 12 strResult = Convert.ToString(Operation.GetResult(Convert.ToDouble(strNumA), Convert.ToDouble(strNumB), strOperate)); 13 Console.WriteLine($"結果是:{strResult}"); 14 Console.ReadKey(); 15 } 16 catch (Exception ex) 17 { 18 Console.WriteLine($"您的輸入有錯:{ex.Message}"); 19 } 20 }
這樣的話,無論是控制台,還是Winform以及其他應用,只需要調用 Operation 這個類即可了。實現了業務邏輯與界面的分離。這裡,也用到了面向對象編程的三大特性之一的封裝。
3、第三步演繹
①如果我想增加一種計算方式,例如開根號(sqrt)運算怎麼辦,只能是修改Operation類,在switch中增加一種情況。
②針對①問題做修改的話,那麼另一個問題就來了,我修改Oeration類的時候,之前寫好的加減乘除功能全在其中,如果我不小心,或者有意搞破壞,將本來運行的好好的加減乘除功能改掉,怎麼辦?(此例中僅僅是計算器,如果換做是成熟的產品,或者涉及到資金運算等等的代碼,運行的好好的,不可能會讓程式員在其中胡作非為的)
針對上述問題,作如下修改:
我可以將加減乘除各種運算分別封裝到不同的類裡面,這樣,就能解決②的問題,每增加一種運算,我就增加一個類,這樣①問題也解決了。
首先,將不同的運算抽象出一個共同的類,即父類
1 public class Operation 2 { 3 private double _numberA = 0; 4 private double _numberB = 0; 5 public double NumberA 6 { 7 get 8 { 9 return _numberA; 10 } 11 12 set 13 { 14 _numberA = value; 15 } 16 } 17 public double NumberB 18 { 19 get 20 { 21 return _numberB; 22 } 23 24 set 25 { 26 _numberB = value; 27 } 28 } 29 public virtual double GetResult() 30 { 31 double result = 0; 32 return result; 33 } 34 }
其次,讓不同的運算繼承這個父類,然後根據不同的運算,重寫父類中的GetResult方法
1 //加法類 2 public class OperationAdd:Operation 3 { 4 public override double GetResult() 5 { 6 double result = 0; 7 result = NumberA + NumberB; 8 return result; 9 } 10 } 11 //減法類 12 public class OperationSub : Operation 13 { 14 public override double GetResult() 15 { 16 double result = 0; 17 result = NumberA = NumberB; 18 return result; 19 } 20 } 21 //乘法類 22 public class OperationMul : Operation 23 { 24 public override double GetResult() 25 { 26 double result = 0; 27 result = NumberA * NumberB; 28 return result; 29 } 30 } 31 //除法類 32 public class OperationDiv : Operation 33 { 34 public override double GetResult() 35 { 36 double result = 0; 37 if (NumberB==0) 38 { 39 throw new Exception("除數不能為0"); 40 } 41 result = NumberA / NumberB; 42 return result; 43 } 44 }
這樣,上述的兩個問題就迎刃而解了。
4、第四步演繹
到了簡單工廠最核心的地方了。
這麼多的類,客戶端該如何用這些類呢,換句話說,客戶端如何實例化這些類呢?那麼,就需要一個核心的東西——工廠,這個工廠負責給客戶端提供他想要的類的實例。我想要實例化什麼類,告訴工廠就可以了。
代碼如下:
1 public class OperationFactory 2 { 3 public static Operation createOperate(string operate) 4 { 5 Operation oper = null; 6 switch (operate) 7 { 8 case "+": 9 oper = new OperationAdd(); 10 break; 11 case "-": 12 oper = new OperationSub(); 13 break; 14 case "*": 15 oper = new OperationMul(); 16 break; 17 case "/": 18 oper = new OperationDiv(); 19 break; 20 } 21 return oper; 22 } 23 }
註意一點,這個工廠中的方法,返回的是加減乘除這些類的父類。
好了,製造類實例的工廠有了,那麼,客戶端只需要告訴工廠,給我造一個什麼類的實例,然後用這個實例就可以了。
客戶端代碼如下
1 static void Main(string[] args) 2 { 3 Operation oper; 4 //告訴工廠,給我一個加法類的實例 5 oper = OperationFactory.createOperate("+"); 6 oper.NumberA = 1; 7 oper.NumberB = 2; 8 double result = oper.GetResult(); 9 Console.WriteLine(result); 10 Console.ReadKey(); 11 }
經過上述一系列的演繹,也就形成了簡單工廠模式。
三、總結
簡單工廠模式,即 通過一個‘工廠類’,用於子類返回父類對象。
工廠模式結束,下一次,將講解策略模式