最近在看程杰的《大話設計模式》,在這里做一點筆記。
書中主要有兩個角色:
小菜:初學者,學生;
大鳥:小菜表哥,大佬。
也按圖中的對話形式
01 簡單工廠模式
要求:使用c++、Java、C#或VB.NET任意一種面向對象語言實現一個計算器控制臺程序,要求輸入兩個數和運算符號,得到結果。
小菜的代碼:
大鳥指出部分問題:
- A, B, C, D 這樣的命名不規范;
- if的判斷分支,邏輯有誤,且未考慮除數輸入為0/輸入為字符非數字等等。
小菜對代碼進行修改:
修改后的邏輯基本沒有問題了,但是并沒有面向對象。
如何設計出容易維護,容易擴展,又容易復用的計算器程序呢?
程序要避免重復。
小菜:那就是分類,將計算和顯示分開?
大鳥:準確說,是讓業務邏輯與界面邏輯分開,讓它們之間的耦合度下降。只有分離開,才可以達到容易維護或擴展。
接下來,小菜重新進行了嘗試:
運算類:
main函數:
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 = "";strResult = Convert.ToString(Operation.GetResult(Convert.ToDouble(strNumberA),Convert.ToDouble(strNumberB), strOperate));Console.WriteLine("結果是:" + strResult);Console.ReadLine();}catch (Exception ex){Console.WriteLine("您的輸入有錯:" + ex.Message);}
}??
目前,無論在windows,還是在web,手機端都可以在需要運算時使用上面運算類的定義。
這里使用到的是“面向對象”的封裝。
提問:如何更靈活的修改和擴展代碼呢?比如,現在希望增加一個開根號(sqrt)的運算。
小菜:直接修改Operation類?
大鳥:但問題是,要加一個平方根運算,卻需要讓加減乘除的運算都得來參與編譯。而且還可能讓原有的運行良好的功能代碼產生了變化,這個風險太大了
因此,需要盡量把加減乘除等運算分離,修改其中一個不影響其他
小菜進行新嘗試:
operation運算類:
public class Operation
{private double _numberA = 0;private double _numberB = 0;public double NumberA{get { return _numberA; }set { _numberA = value; }}public double NumberB{get { return _numberB; }set { _numberB = value; }}public virtual double GetResult(){double result = 0;return result;}
}??
兩個Number屬性,主要用于計算器的前后數,然后有一個虛方法GetResult(),用于得到結果。
加減乘法類:
加減乘除都寫成了運算類的子類,繼承它后,重寫了GetResult()方法,這樣如果要修改任何一個算法,就不需要提供其他算法的代碼了。
但是,如何讓計算器知道我是希望用哪一個算法呢?
考慮用一個單獨的類來做這個創造實例的過程,這就是“工廠”
進行如下設置:
此時,只需要輸入運算符號,工廠就實例化出合適的對象。
一個實例:
Operation oper;
oper = OperationFactory.createOperate(“+”);
oper.NumberA = 1;
oper.NumberB = 2;
double result = oper.GetResult();??
此時,例如要修改加法運算,改OperationAdd即可。
如果需要增加各種復雜運算,增加相應的運算子類,并在switch中增加分支。