设计模式实践---策略模式实现对大量计算公式的处理

发布时间 2023-03-22 19:08:02作者: 守护月亮的星星

业务流程:

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 Program
    {
        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((AbstractFormula)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(schemeinformation.Formula));
                //获取当前公式的计算结果集
                List<string>tempResults=context.Caclute(schemeinformation);
                //遍历结果,将所有结果放入到总结果集中
                foreach(string tempResult in tempResults)
                {
                    results.Add(new Result(schemeinformation,tempResult));
                }
            }
            //下面就可以输出总结果集了
            Console.WriteLine(results.Count);
        }
    }