本文將介紹簡單工廠模式
1. 面向過程的計算器
static void Main(string[] args)
{
//面向過程的計算器
try
{
Console.WriteLine("請輸入數字A: ");
string strNumA = Console.ReadLine();
Console.WriteLine("請選擇運算符號(+、-、*、/): ");
string strOperate = Console.ReadLine();
Console.WriteLine("請輸入數字B: ");
string strNumB = Console.ReadLine();
string strResult = string.Empty;
switch (strOperate)
{
case "+":
strResult = (Double.Parse(strNumA) + Double.Parse(strNumB)).ToString();
break;
case "-":
strResult = (Double.Parse(strNumA) - Double.Parse(strNumB)).ToString();
break;
case "*":
strResult = (Double.Parse(strNumA) * Double.Parse(strNumB)).ToString();
break;
case "/":
if (Double.Parse(strNumB) == 0)
{
throw new Exception("被除數不能為0!");
}
strResult = (Double.Parse(strNumA) / Double.Parse(strNumB)).ToString();
break;
default:
throw new Exception("運算符輸入錯誤!");
}
Console.WriteLine(strNumA + " " + strOperate + " " + strNumB + " = " + strResult);
}
catch (Exception ex)
{
Console.WriteLine("您輸入的有錯:" + ex.Message);
}
Console.ReadKey();
}
思考:
上面的計算器是Console版的,如果我要實現WinForm版、Web版、手機版。那怎麼辦呢?
Ctrl-C, Ctrl-V是一種方法(我剛寫代碼的時候就是這麼辦的)。但是當重復的代碼多了,維護起來,可能就是一場災難。
這時面向對象的優勢就體現出來了,把計算器的功能封裝成一個計算器類,供Console, WinForm, Web等調用。將來要維護,只維護這一個類即可。
2. 面向對象1: 封裝 - 將計算和顯示分開
//業務的封裝 - 計算
public class Operation
{
public static double CalcResult(double numA, double numB, string op)
{
double result = 0d;
switch (op)
{
case "+":
result = numA + numB;
break;
case "-":
result = numA - numB;
break;
case "*":
result = numA * numB;
break;
case "/":
if (numB == 0)
{
throw new Exception("被除數不能為0!");
}
result = numA / numB;
break;
default:
throw new Exception("運算符輸入錯誤!");
}
return result;
}
}
//客戶端代碼 - 界面
static void Main(string[] args)
{
try
{
Console.WriteLine("請輸入數字A: ");
string strNumA = Console.ReadLine();
Console.WriteLine("請選擇運算符號(+、-、*、/): ");
string strOperate = Console.ReadLine();
Console.WriteLine("請輸入數字B: ");
string strNumB = Console.ReadLine();
string strResult = Operation.CalcResult(double.Parse(strNumA), double.Parse(strNumB), strOperate).ToString();
Console.WriteLine(strNumA + " " + strOperate + " " + strNumB + " = " + strResult);
}
catch (Exception ex)
{
Console.WriteLine("您輸入的有錯:" + ex.Message);
}
Console.ReadKey();
}
思考:
如果現在要加一個平方根運算,怎麼辦?看來只能改Operation類了,那麼已經寫好的加減乘除運算代碼是不是也會暴露出來,面臨著被誤修改的風險(如果這個類是計算工資的類,那風險得多大)。而且添加完平方根後,整個類都要重新編譯,豈不是很麻煩。
看來上面的實現擴展性和靈活性還是不夠好,需要再設計一下。
3. 面向對象2:封裝、繼承、多態 - 簡單工廠模式
/// <summary>
/// 抽象類:運算類
/// </summary>
public class Operation
{
private double _numA = 0;
private double _numB = 0;
public double NumA
{
get { return _numA; }
set { _numA = value; }
}
public double NumB
{
get { return _numB; }
set { _numB = value; }
}
public virtual double GetResult()
{
return 0;
}
}
/// <summary>
/// 加法 : 繼承運算類
/// </summary>
public class OperationAdd : Operation
{
public override double GetResult()
{
return NumA + NumB;
}
}
/// <summary>
/// 減法 : 繼承運算類
/// </summary>
public class OperationSub : Operation
{
public override double GetResult()
{
return NumA - NumB;
}
}
/// <summary>
/// 乘法 : 繼承運算類
/// </summary>
public class OperationMul : Operation
{
public override double GetResult()
{
return NumA * NumB;
}
}
/// <summary>
/// 除法 : 繼承運算類
/// </summary>
public class OperationDiv : Operation
{
public override double GetResult()
{
if (NumB == 0)
throw new Exception("被除數不能為0");
else
return NumA / NumB;
}
}
/// <summary>
/// 工廠 : 生產計算器
/// </summary>
public class OperationFactory
{
public static Operation createOperation(string op)
{
Operation oper = null;
switch (op)
{
case "+":
oper = new OperationAdd();
break;
case "-":
oper = new OperationSub();
break;
case "*":
oper = new OperationMul();
break;
case "/":
oper = new OperationDiv();
break;
default:
throw new Exception("操作符錯誤,只支持+-*/四則運算。");
}
return oper;
}
}
/// <summary>
/// 客戶端
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
try
{
Console.WriteLine("請輸入數字A: ");
string strNumA = Console.ReadLine();
Console.WriteLine("請選擇運算符號(+、-、*、/): ");
string strOperate = Console.ReadLine();
Console.WriteLine("請輸入數字B: ");
string strNumB = Console.ReadLine();
Operation oper = OperationFactory.createOperation(strOperate);
oper.NumA = double.Parse(strNumA);
oper.NumB = double.Parse(strNumB);
string strResult = oper.GetResult().ToString();
Console.WriteLine(strNumA + " " + strOperate + " " + strNumB + " = " + strResult);
}
catch (Exception ex)
{
Console.WriteLine("您輸入的有錯:" + ex.Message);
}
Console.ReadKey();
}
思考:
現在的計算器通過封裝、繼承、多態把程序的耦合度降低,更加的靈活,容易修改,易於服用。