zoukankan      html  css  js  c++  java
  • 用反射或委托优化switch太长的方法

      在代码进行优化的时候,发现了switch case太长,有的竟然长达30个远远超过一屏这样在代码的可读性来说很差。特别在我们看代码的时候要拉下拉框我个人觉得这是不合理的。但是我不建议有switch就进行反射或委托来解决。看实际的情况比喻10个以为还是可以接受的。因为switch看起来更加的直接而且效率相对来说是最好的。那下面就用代码来一点点进行解释

    1:传统的用法

    1.1:现在我们有一个需求通过传递参数来获取相关的信息。首先我们先看方法

     1 public class SwitchMethod {        
     2         public string GetSerialNumber(string serialNumber)
     3         {
     4             return serialNumber;
     5         }
     6 
     7         public string GetName(string name)
     8         {
     9             return name;
    10         }
    11 
    12         public string GetAge(string age)
    13         {
    14             return age;
    15         }
    16 
    17         public string GetBirthday(string birthday)
    18         {
    19             return birthday;
    20         }
    21 
    22     }
    调用的方法

    1.2:客户端的调用

     1 string action =Console.ReadLine() ;
     2             var switchMethod=new SwitchMethod();
     3             switch (action)
     4             {
     5                 case "serialNumber":
     6                 Console.WriteLine(switchMethod.GetSerialNumber("1234"));    
     7                     break;
     8                 case "name":
     9                     Console.WriteLine(switchMethod.GetName("zhangsan"));
    10                     break;
    11                 case "age":
    12                     Console.WriteLine(switchMethod.GetAge("21"));
    13                     break;
    14                 case "birthday":
    15                     Console.WriteLine(switchMethod.GetBirthday("19960201"));
    16                     break;
    17             }
    客户端调用

    1.3:效果

    以上是我们最常规的用法看起来最直观但是你想过没有如果有30个方法呢你还这样进行switch case吗 50,100个呢所以下面我用委托来代码

    2:委托替代switch

    上面我又发现一个问题action凌乱,如果太多了就搞不清什么是什么了所以我们加入枚举

    2.1:建立枚举

     1 public enum ActionEnum
     2     {
     3         /// <summary>
     4         /// 编号
     5         /// </summary>
     6         SerialNumber = 0,
     7         /// <summary>
     8         /// 姓名
     9         /// </summary>
    10         Name = 1,
    11         /// <summary>
    12         /// 年龄
    13         /// </summary>
    14         Age = 2,
    15         /// <summary>
    16         /// 生日
    17         /// </summary>
    18         Birthday = 3
    19     }
    action枚举

    2.2:我采取字典把需要switch的都存起来

     1 private static void LoadDictionary()
     2         {
     3             if (AllDictionary.Count<=0)
     4             {
     5                 var switchMethod = new SwitchMethod();
     6                 AllDictionary.Add(ActionEnum.SerialNumber, switchMethod.GetSerialNumber);
     7                 AllDictionary.Add(ActionEnum.Age, switchMethod.GetAge);
     8                 AllDictionary.Add(ActionEnum.Birthday, switchMethod.GetBirthday);
     9                 AllDictionary.Add(ActionEnum.Name, switchMethod.GetName);
    10             }            
    11         }
    字典保存

    2.3:建立委托(这是比较简单的其实在方法中还可以提取相似的操作放在委托执行)

    1 public static string Exec(string str,Func<string, string> method) {
    2             return method(str);
    3         } 
    委托

    2.4:客户端调用

    1 Console.WriteLine(Exec("21", AllDictionary[ActionEnum.Age]));
    客户端调用

    2.5:效果

    3:反射替代switch

     3.1建立一个自定义Attribute类(目的是为了附带方法中的信息)

    1 public class MethodAttribute : Attribute
    2     {
    3         public ActionEnum MethodName;
    4 
    5         public MethodAttribute(ActionEnum methodName)
    6         {
    7             this.MethodName = methodName;
    8         }
    9     }
    特性类

    3.2:定义一个基类

     1 public class BaseMethod
     2     {
     3         public Hashtable GetMethodAttribute<T>(T t)
     4         {
     5             var hashtable = new Hashtable();
     6             Type type = t.GetType();            
     7             foreach (MethodInfo method in type.GetMethods())
     8             {
     9                 var methodArray = (MethodAttribute[]) method.GetCustomAttributes(typeof (MethodAttribute), false);
    10                 foreach (MethodAttribute actionMethodAttribute in methodArray)
    11                 {
    12                     ActionEnum actionName = actionMethodAttribute.MethodName;
    13                     hashtable.Add(actionName, method);
    14                 }
    15             }
    16             return hashtable;
    17         }
    18 
    19         
    20         public string DoAction(ActionEnum actionName,string str) {
    21             Hashtable ht = GetMethodAttribute(this);
    22             string message = ht.Contains(actionName)
    23                 ? ((MethodInfo) ht[actionName]).Invoke(this, new object[] {str}).ToString()
    24                 : string.Format("{0} 超过范围", actionName);
    25             return message;
    26         }
    27     }
    基类

    3.3:修改SwitchMethod类并给方法加上特性

     1     public class SwitchMethod : BaseMethod
     2     {
     3         [Method(ActionEnum.SerialNumber)]
     4         public string GetSerialNumber(string serialNumber)
     5         {
     6             return serialNumber;
     7         }
     8 
     9         [Method(ActionEnum.Name)]
    10         public string GetName(string name)
    11         {
    12             return name;
    13         }
    14 
    15         [Method(ActionEnum.Age)]
    16         public string GetAge(string age)
    17         {
    18             return age;
    19         }
    20 
    21         [Method(ActionEnum.Birthday)]
    22         public string GetBirthday(string birthday)
    23         {
    24             return birthday;
    25         }
    26     }
    SwitchMethod 类

    3.4:客户端调用

    string result = new SwitchMethod().DoAction(ActionEnum.SerialNumber,"1332");

    3.5:注释

    3.5.1:type.GetMethods():获取这个类中所有的方法包括基类的方法

    3.5.2:method.GetCustomAttributes(typeof (MethodAttribute), false):获取这个方法所有关于MethodAttribute类型的自定义特性

    3.5.3:MethodInfo:表示对类中方法的访问

    3.6:运行效果

    三种方式总结 

    1:传统的用法

    优点:简单易读,效率高

    缺点:当量很多的时候会造成方法很长,不易维护,可能修改其中某一个case会引起未知的错误

    2:委托

    优点:使用委托将公有的进行提取,减少代码量

    缺点:加入字典后每次添加都需要在字典后手动添加一个子项。总是觉得别扭,效率稍微差点

    3:反射

    优点:代码量减少,不在考虑内部如何实现,而且符合开闭原则,只需要添加新的方法,其他地方不作修改。维护性强

    缺点:很明显这个效率最差(此处并未加入缓存)

    第三种方式参考:http://www.cnblogs.com/vipsoft/archive/2012/10/19/2731126.html

  • 相关阅读:
    JUnit4的使用
    Android中使用JUnit4测试发生fatal error
    计算器的M+是什么意思
    初识Ildasm.exe——IL反编译的实用工具
    jsp下载
    jsp文件上传
    java.sql.SQLException: Io 异常:
    在PowerDesigner中创建物理模型时DBMS选项为空
    oracle10g还原被drop的表
    oracle创建用户
  • 原文地址:https://www.cnblogs.com/LipeiNet/p/4975672.html
Copyright © 2011-2022 走看看