設計模式實踐---策略+簡單工廠對大量計算公式的處理

2023-01-05 15:00:54

業務流程:

1.使用者根據需要選擇的實驗方案,每個實驗方案對應一種計算公式,計算公式例如下面這種

 

 2.將帶有實驗資料的PDF檔案上傳到特定位置,對PDF檔案進行解析後將資料資料儲存到資料庫。

3.遍歷所有方案,對每種方案使用特定的公式對資料庫中的資料進行

重構前實現:

遍歷方案,使用IF語句對使用的公式進行判斷,而後在IF塊裡對資料進行處理

IF(Formula=='F1'){
    //F1的處理...
}
IF(Formula=='F2'){
    //F2的處理...
}
IF(Formula=='F3'){
    //F2的處理...
}

這樣實現的問題就是程式太過龐大,八十多個公式就要有八十多個判斷語句,並且判斷內部的處理現也是很龐大的,這就導致了這個程式可讀性很差,維護以及偵錯都十分困難。

重構

這裡考慮使用策略模式+簡單工廠進行重構

策略模式(Strategy Pattern):定義一系列演演算法,將每一個演演算法封裝起來,並讓它們可以相互替換。策略模式讓演演算法獨立於使用它的客戶而變化。

使用策略模式重構後的程式結構:

定義一個AbstractFormula抽象類,在抽象類中定義一個Calculation計算方法,這個方法返回經過計算的結果的集合,在各個實現類(即具體公式)中實現Calculation方法

定義上下文類,在上下文類中指定要使用的公式,定義Caclute方法用於返回結果。

實現程式碼

    /// <summary>
    /// 簡易的方案資訊
    /// </summary>
    internal class Schemeinformation
    {
        //方案ID
        public string SchemeID { get; set; }
        //方案名稱
        public string SchemeName { get; set; }
        //公式
        public string Formula { get; set; }
    }
    /// <summary>
    /// 單個結果
    /// </summary>
    internal class Result
    {
        public Result(Schemeinformation schemeinformation, string 
        Result)
        {
            Schemeinformation = schemeinformation;
            FinalResult=Result;
        }
        public string FinalResult { get; set; }

        public Schemeinformation Schemeinformation { get; set; }
    }
//抽象的公式類   
 internal abstract class AbstractFormula
    {
        //公式計算後的結果集
        public List<string>? tempResultList;
        public abstract List<string> Caclution(Schemeinformation 
        schemeinformation);
    }
//具體實現    
internal class Formula1 : AbstractFormula
    {
        public override List<string> Caclution(Schemeinformation schemeinformation)
        {
            tempResultList = new List<string>();
            //計算過程... 對tempResultList賦值
            return tempResultList;
        }
    }
    internal class Formula2 : AbstractFormula
    {
        public override List<string> Caclution(Schemeinformation schemeinformation)
        {
            tempResultList = new List<string>();
            //計算過程...其中需要使用到Schemeinformation中的資訊
            //對tempResultList賦值
            return tempResultList;
        }
    }
    /// <summary>
    /// 上下文類 使用公式,並管理結果集
    /// </summary>
    internal class Context
    {
        AbstractFormula formula;
        public void SetFromula(AbstractFormula formula)
        {
            this.formula = formula;
        }
        public List<string> Caclute(Schemeinformation schemeinformation)
        {
            return formula.Caclution(schemeinformation);
        }
    }
    /// <summary>
    /// 建立公式的簡單工廠
    /// </summary>
    internal class FormulaFactory
    {
        public static AbstractFormula GetFormula(string Formula)
        {
            if(Formula == "F1")
            {
                return new Formula1();
            }
            else if(Formula == "F2")
            {
                return new Formula2();
            }
            //以下若干.....

            else
            {
                //找不到這個公式,丟擲異常
                throw new ArgumentNullException("value", $"公式{Formula}不存在"); ;
            }
            
        }
    }
//實際使用      
 static void Main(string[] args)
        {
            Context context= new Context();
            //獲取所有方案資訊
            List<Schemeinformation> schemeinformationList = new List<Schemeinformation>();
            //總結果集
            List<Result> results= new List<Result>();

            foreach(Schemeinformation schemeinformation in schemeinformationList)
            {
                //使用簡單工廠獲得公式物件
                context.SetFromula(FormulaFactory.GetFormula(schemeinformation.Formula));
                //獲取當前公式的計算結果集
                List<string>tempResults=context.Caclute(schemeinformation);
                //遍歷結果,將所有結果放入到總結果集中
                foreach(string tempResult in tempResults)
                {
                    results.Add(new Result(schemeinformation,tempResult));
                }
            }
            //下面就可以輸出總結果集了
            Console.WriteLine(results.Count);
        }