在C#工厂方法中避免使用多个if语句

时间:2015-07-30 06:22:07

标签: c# if-statement orm solid-principles

我有C# application将数据存储在NoSQL database中。该应用程序有一个存储库类,它使用一系列对象将数据从NoSQL表单转换为C#模型使用的数据,反之亦然(实质上是一种ORM形式)。对象实现converter接口,每个对象在一个特定的data type (string, bool, etc)上工作。在内部,他们使用反射来执行转换。这些对象的实例由返回给定类型的对象的方法创建。目前,逻辑类似于以下内容:

if(type == typeof(string)
    return new StringConverter(...);

if(type == typeof(int) || type == typeof(uint))
    return new IntegerConverter(...);

... // and so on

然而,所有这些if陈述都困扰着我。我知道我可以做一些事情,比如创建一个字典来将类型映射到创建方法,但我不确定这是否会产生更易读,易于维护/扩展的代码(?)。鉴于需要创建类型抽象,最好的方法是什么?欢迎任何建议。非常感谢提前。

4 个答案:

答案 0 :(得分:1)

理想情况下,嵌套if-statements是您要避免的。我引用微软的完整代码书。这个想法是当你最多嵌套3个级别时,维护代码的开发人员或开发人员的注意力会大大降低。 在您的情况下,如果您的逻辑必须是硬编码的,则无法使用if语句序列。然而,巧妙的解决方法是遵循工厂设计模式。(Gangs of Four)

答案 1 :(得分:1)

您应该将if代码导出到工厂类。

正如您所见here,工厂是一个产生的GoF模式 不同种类的物体。

在工厂类中,这个int情况的数量是可以的。

你应该只避免使用嵌套的if语句,它们会使你的代码不可读

答案 2 :(得分:1)

就可读性而言,您应该更喜欢

switch(type.FullName){
  case(typeof(int).FullName) => //your logic
  ...
}

switch-case-Statement更可读代码而不是If-Else并且可以更快。 HERE您可以阅读更多相关信息:

  

对于少数项目,差异很小。如果你有很多物品,你一定要使用开关。

     

如果一个开关包含五个以上的项目,则使用一个   查找表或哈希列表。这意味着所有项目都相同   访问时间,与if:列表相比,最后一项需要多少   更多时间到达,因为它必须评估每个先前的条件   第一

正如其他人已经说过的那样,将您的switch-case外包给工厂类。

答案 3 :(得分:0)

我相信你将这些类型映射到字典的想法是你最好的选择,因为它实现了一种策略模式,并且本身就具有很强的表现力。

<cfloop from="1" to="5" index="k">
    <cfloop from="#qry.S#" to="#qry.E#" index="i" step="#CreateTimeSpan(0,0,qry.Leng,0)#">
        <cfset TimeEnd = dateAdd("n", Leng, i)>
            <tr>
                <td>(#k#) #timeFormat(TimeStart, "hh:mm tt")# - #timeFormat(TimeEnd, "hh:mm tt")#</td>
            </tr>
        <cfset TimeStart = dateAdd("n", qry.Leng, i)>           
    </cfloop>   
</cfloop>

然后在传入引用类型时使用TryGetValue。

您可能会考虑让这个字典成为该类的私有成员,并在初始化包含类时填充它。

Gary McLean Hall在他的“自适应代码”一书中通过C#演示了这种模式,它在这样的情况下给了我很多帮助!