• 选择结构(if..else..,switch,try..catch..)的拆分


    编程中经常遇到很多条件,以及条件套条件的情况,以至于一个方法会写得非常地长。有多种方法可以规避这个问题。比如反射,策略模式,表驱动等等。先抛开这些方法不讲,从根本需求来探索这个过程。

    一个switch结构可能是这样:

    swicth(case)

      case 1:

        //do1

        break;

      case 2:

        //do2

        break;

      .....

    这里注释的do部分代码可能会是很多很多行,以及嵌套switch,if结构。

    进一步,这个模型演化成

    swicth(case)

      case 1:

        do1();

        break;

      case 2:

        do2();

        break;

      .....

    do1(){}

    do2(){}

    也就是将里面的代码模块化。这个方法有效的减小了一个方法的代码长度。实际上这就是一个映射关系的调用。建立映射关系,用Hash结构和delegate就可以避免使用switch了。

    delegate void funtionptr();

    Dictionary<int, funtionptr> dict = new Dictionary<int, funtionptr>();

    dict.Add(1,do1);

    dict.Add(2,do2);

    int parm = 0;

    if(dict.ContainKey(parm)){

      dict[parm].Invoke();

    do1(){}

    do2(){}

    这个方法实际上就是表驱动,因为C#中一般不用指针,因此用delegate代替了指针的作用。而java中既没有指针也没有delegate怎么办呢?那就用接口模拟指针。

    (这里就用C#的语法了,不使用JAVA了)

    interface FactionFace{

      void do();

    class FactionFaceImpl1 : FactionFace{

      public void do(){}

    class FactionFaceImpl2 : FactionFace{

      public void do(){}

    Dictionary<int, FactionFace> dict = new Dictionary<int, FactionFace>();

    dict.Add(1,new FactionFaceImpl1());

    dict.Add(2,new FactionFaceImpl2());

    int parm = 0;

    if(dict.ContainKey(parm)){

      dict[parm].do();

    可以看出,实际上,上面的代码就是策略模式的简单实现了。(OH~~原理策略模式这么就来的~~)

    可以看出,这里实际上是依靠一个字典来维护条件和调用的关系的。那如果没有这个字典来维护怎么办呢?代码再次演化:

    interface FactionFace{

      void do();

    class FactionFaceImpl1 : FactionFace{

      public void do(){}

    class FactionFaceImpl2 : FactionFace{

      public void do(){}

    string parm = "FactionFaceImpl2";

    FactionFace ff = Type.GetType(parm) as FactionFace;

    ff.do();

    OH~~这就是简单的反射了。再复杂一些就可以搞成工厂模式,插件模式了。

    可以看出,用字典来维护映射关系就可以避免使用反射。(这个是不是一般规律,贫道没本事证明,起码这里是适应的。)

    再来看try...catch...

    delegate void forException(Exception ex);

    public void forAException(Exception ex) {Console.WriteLine("AException");}
    public void forAAException(Exception ex) {Console.WriteLine("AAException");}
    public void forBException(Exception ex) {Console.WriteLine("BException");}

    public void test() {

      Dictionary<int, forException> dict = new Dictionary<int, forException>();

      dict.Add(0, forAException);

      dict.Add(1, forAException);

      dict.Add(11, forAAException);

      dict.Add(2, forBException);

      try {

        throw new AAException();

      } catch (Exception ex) 

      {

        if (ex is OException) {

          OException eex = ex as OException;

          if (dict.ContainsKey(eex.Index)) {

             dict[eex.Index].Invoke(ex);

          }

        }

      }

    }

    public class OException : Exception {public virtual int Index { get { return 0; } }}
    public class AException : OException {public override int Index {get {return 1;}}}
    public class AAException : AException {public override int Index {get {return 11;}}}
    public class BException : OException {public override int Index {get {return 2;}}

    这里为啥要有个Index属性呢?其实就是建立个对应的关系,而不是靠名字去维护。去掉这个属性,直接使用ex.GeType()然后获取名字类名也一样可以建立对应关系。

  • 相关阅读:
    Linux 日志管理
    Linux 备份与恢复
    Linux 启动管理
    Linux 用户和用户组管理
    产生指定时间区间序列、按指定单位变化时间 python实现
    python上数据存储 .h5格式或者h5py
    数据预处理之独热编码(One-Hot Encoding)
    残差网络
    GBDT为什么不能并行,XGBoost却可以
    百融金服、趣店、中航信面试总结
  • 原文地址:https://www.cnblogs.com/birdshover/p/1894703.html
Copyright © 2020-2023  润新知