[設計模式] 簡單工廠(Simple Factory)
Introduction
(原文出處 大話設計模式 )
大部分的人對於物件導向都有一些了解,利用物件導向的特性(封裝、繼承、多型) 來寫出容易擴充、維護與高重用性的程式,
如同書上介紹的,我想設計模式只是利用物件導向的特性,讓我們去找到「封裝變化」、「物件間鬆散的耦合」、「針對介面程式設計」
的感覺,而達到最終的目的。這是個心得筆記。
Example
寫出一個簡單計算機功能的程式,並且這個程式,可以移植到任何的應用程式(ex:Web、PDA、Window)。
先設計一個 Operation 抽象類別作為基底。
/// <summary>
/// 運算類別
/// </summary>
public abstract class Operation {
private double _numberA = 0;
private double _numberB = 0;
/// <summary>
/// 數字A
/// </summary>
public double NumberA {
get {
return _numberA;
}
set {
_numberA = value;
}
}
/// <summary>
/// 數字B
/// </summary>
public double NumberB {
get {
return _numberB;
}
set {
_numberB = value;
}
}
/// <summary>
/// 得到運算結果
/// </summary>
/// <returns></returns>
public virtual double GetResult() {
double result = 0;
return result;
}
}
再來撰寫計算的功能(加法、乘法...),複寫 GetResult() 函式(屬於自己的計算結果)。
/// <summary>
/// 加法類別
/// </summary>
class OperationAdd : Operation {
public override double GetResult() {
double result = 0;
result = NumberA + NumberB;
return result;
}
}
/// <summary>
/// 減法類別
/// </summary>
class OperationSub : Operation {
public override double GetResult() {
double result = 0;
result = NumberA - NumberB;
return result;
}
}
/// <summary>
/// 乘法類別
/// </summary>
class OperationMul : Operation {
public override double GetResult() {
double result = 0;
result = NumberA * NumberB;
return result;
}
}
/// <summary>
/// 除法類別
/// </summary>
class OperationDiv : Operation {
public override double GetResult() {
double result = 0;
if (NumberB == 0)
throw new Exception("除數不能為0。");
result = NumberA / NumberB;
return result;
}
}
撰寫簡單工廠類別,負責實體化要運算的類別(利用多型的技巧)。
/// <summary>
/// 運算類別工廠
/// </summary>
public class OperationFactory {
public static Operation createOperate(string operate) {
Operation oper = null;
switch (operate) {
case "+": {
oper = new OperationAdd();
break;
}
case "-": {
oper = new OperationSub();
break;
}
case "*": {
oper = new OperationMul();
break;
}
case "/": {
oper = new OperationDiv();
break;
}
case "sqr": {
oper = new OperationSqr();
break;
}
case "sqrt": {
oper = new OperationSqrt();
break;
}
case "+/-": {
oper = new OperationReverse();
break;
}
}
return oper;
}
}
最後就是 Client 端的程式。
static void Main(string[] args) {
try {
Console.Write("請輸入數字A:");
string strNumberA = Console.ReadLine();
Console.Write("請選擇運算符號(+、-、*、/):");
string strOperate = Console.ReadLine();
Console.Write("請輸入數字B:");
string strNumberB = Console.ReadLine();
string strResult = "";
Operation oper;
oper = OperationFactory.createOperate(strOperate);
oper.NumberA = Convert.ToDouble(strNumberA);
oper.NumberB = Convert.ToDouble(strNumberB);
strResult = oper.GetResult().ToString();
Console.WriteLine("結果是:" + strResult);
Console.ReadLine();
}
catch (Exception ex) {
Console.WriteLine("您的輸入有錯:" + ex.Message);
}
}
輸出結果
這個方法切割了介面與演算法,並且依照需求產生相對應的物件,這就是簡單工廠的好處;
若是要擴充運算類別或是修改,也只需針對演算法這一塊,當然,對於判斷建立相對應的運算
物件,還是有缺點,這邊在判斷上就需要花上一些成本,我想很些人會想到 反射 技術。
三小俠 小弟獻醜,歡迎指教