C# 一個計算器功能實現引發的思考
一.需求
計算器功能需求,這個眾所周知,很明確了。
二.步驟分析
1)初級實現計算器
static int Calculator(int a,int b,string str) { switch(str) { case "+": return a + b; case "-": return a - b; case "*": return a * b; case "/": return a / b; } return 0; }
優勢:程式碼簡單。
劣勢:如果新增需求,需要不斷在switch中增加分支,並且需要在對應分支寫上相應的邏輯程式碼。程式碼耦合度太高。違背對修改關閉原則。
2)中級實現計算器
I.先看case分支中對應的操作,都是運算。即,我們可以把其實現抽象出來。
II.因為我們知道所有的運算都是對兩個數進行運算,所以,可以抽象出一個抽象類,即運算抽象基類BaseCalculate。
public abstract class BaseCalculate { public abstract int Calculate(int a, int b); } public class Add : BaseCalculate { public override int Calculate(int a, int b) { return a + b; } } public class Sub:BaseCalculate { public override int Calculate(int a, int b) { return a - b; } }
優勢:這個操作,我們將case中分支的程式碼抽象出來了。在對應的運運算元類中更改其操作就可以。將具體實現抽離出來。
劣勢:程式碼量增加,違背了開放-封閉原則。(即開放增加,封閉修改原則)
上述,就是設計模式中,傳說的簡單工廠模式
3)高階實現計算器
class Program { static void Main(string[] args) { BaseFactory factory = new AddFactory(); Console.WriteLine(factory.GetCalculate().Calculate(2, 1)); BaseFactory factory2 = new SubFactory(); Console.WriteLine(factory2.GetCalculate().Calculate(2, 1)); Console.Read(); } } public abstract class BaseFactory { public abstract BaseCalculate GetCalculate(); } public class AddFactory:BaseFactory { public override BaseCalculate GetCalculate() { return new Add(); } } public class SubFactory:BaseFactory { public override BaseCalculate GetCalculate() { return new Sub(); } }
這就是傳說中工廠方法模式,與上述簡單工廠模式對比克服了開放-封閉原則。
優勢:減去核心邏輯中的switch分支。
劣勢:程式碼量又增加了。
4)擴充套件&補充
如果說上述的設計只為int型運算,如果現在需求增加,還需要增加 專門精度為float計算的計算器。上述計算,只針對int型,現在要專門是float型,該如何?
所以,我們只需要增加基類BaseFloatCalculate,然後進行各種實現。並在BaseFactory中增加 BaseFactory GetFloatCalculate() 即可。程式碼就不貼了,這其實就是擴充套件。
這就是抽象工廠模式。
即使上述種種,還是離不開switch分支問題,有可以解決分支問題的辦法嗎。有的,但是不算主流,可以利用反射。
BaseCalculate cal = (BaseCalculate)Assembly.Load("ConsoleApp7").CreateInstance("ConsoleApp7.Sub"); Console.WriteLine( cal.Calculate(2, 1));
三.總結
所謂優秀的功能的實現程式碼,即需要符合高聚酯,低耦合。
符合高聚酯,低耦合,那就離不開架構設定。
架構設計,其實無非就是即不斷的抽象,對類抽象,對方法抽象。當然,也不能過度抽象,會造成冗餘。
因此總結一下,架構設定,就是合理適度的抽象。
筆者認為
沒有絕對適合某功能的架構框架,只有絕對合理適度的抽象。