如何最好地重构嵌套的switch语句?

时间:2014-03-08 18:01:56

标签: c# wpf oop refactoring

好的,这是我的问题。

基本上有一个像这样的结构(常规表):

   | a1 | a2 | a3 | a4 
----------------------
b1 | v1 | v2 | v3 | v4
----------------------
b2 | v5 | v6 | v7 | v8
----------------------
b3 | v9 | vA | vB | vC

大气压。 a值在枚举(enumA)内,也是b值(enumB) a1 - a4可以通过与枚举绑定的组合框选择,对于b1 - b3也是如此。

基于两者的选择我具有分配给aXbY组合的特定值并返回以进行进一步计算。 这些值是通过嵌套的switch语句选择的,如下所示:

switch (enumA) {
   case a1:
       switch (enumB) {
           case b1: return v1;
           case b2: return v2;

等等。

我想知道的是如何最好地重构我的代码以提高代码质量。 编辑:我正在寻找面向对象的解决方案!

注意:我根本不希望a或b增长。然而,让我假设我处于我所处的境地。让我们假设我希望enumA比enumB更有可能增长。

到目前为止我的意思是:

策略模式硬核一路

我可以将每个“ab”组合重构为它自己的类型,它实现了一个公共接口,每个类型都返回正确的值。

专业人士:

  • 没有嵌套的爆炸开关声明。
  • 开放闭合原则yay。
缺点:

  • 对于每种组合来说都是一种类型的矫枉过正。
  • 我会失去结构,因为理论上我可以有a1b4组合而没有等效的a2b4等等。

enumA的策略模式,enumB的精确方法

我可以将a1-aN重构为类型,它们都实现了相同的接口,它有三个方法getB1,getB2,getB3返回适当的值。

专业人士:

  • 我可以丢掉外部开关。
  • 我可以使用通用接口强制执行表结构。

缺点:

  • 违反开放式封闭原则,因为我必须在新b值进入后更改界面,并使用该界面调整每种类型。
  • 我仍然使用内部switch语句来评估要选择的方法。

我的情况有更好的模式吗?有没有办法保持灵活性,同时仍然执行表结构?如果我使用类型而不是枚举,如何转换到UI?使用反射来获取实现某个接口的每个类并在组合框中显示名称(或任何属性)?

2 个答案:

答案 0 :(得分:2)

由于你有一个表结构,我会将所有v值放在一个多维数组中:
 vType[,] multiArray = new vType[aLength, bLength];

因为所有枚举的基值都是整数(默认为int),所以可以将选定的枚举转换为整数。 enumA会给你列索引和enumB行索引。现在,您可以在一行代码中返回v

return multiArray[(int)enumA, (int)enumB];

没有开关案例,没有接口,没有单独的类型。如果a or b增长,那么您根本不必更改代码(非常)......

答案 1 :(得分:1)

我宁愿在这里使用Dictionary而不是Switch-case,其中Key将是'enumA'和'enumB'的组合,value将是v1(v2,v3 ......)

public class CombinedKey {
  private enumA _enumAValue;
  private enumB _enumBValue;

  override Equals..
  override GetHashCode..

}

public class MainProgram {
   private Dictionary<CombinedKey,SomeValue> _combinedKey2Value = new Dictionary<CombinedKey,SomeValue);

   /// Populate this dictionary based on your Switch-case logic

   public bool TryGetValue(enumA enumAValue, enumB enumBValue, out SomeValue someValue){
          var combinedKey = new CombinedKey(enumAValue, enumBValue);
          return _combinedKey2Valye.TryGetValue(combinedKey, out someValue);

    }
}