【问题标题】:Long list of if comparisons in javajava中if比较的长列表
【发布时间】:2013-12-26 10:01:10
【问题描述】:

我需要比较两个对象。如果有差异,我需要根据特定差异记录它并返回 true。

例如:

private boolean compTwoObjects(Object objA, Object ObjB) {
   if(objA.getType() != objB.getType()) {
      logTheDifference("getType is differing");
      return true;
   }
                   .
                   .
                   .
   // Now this could invoke other composite methods
   if(checkFont(objA.getFont(), objB.getFont()) {
      logTheDifference("Font is differing");
      return true;
   }
}


private boolean checkFont(Font fontObjA, Font fontObjB) {
   if(fontObjA.getBold() != fontObjB.getBold()) {
      logTheDifference("font bold formatting differs");
      return true;
   }
                   .
                   .
                   .
   if(fontObjA.getAllCaps() != fontObjB.getAllCaps()) {
      logTheDifference("font all caps formatting differs");
      return true;
   }
                   .
                   .
                   .
   if(checkBorderDiff(fontObjA.getBorder(), fontObjB.getBorder())) {
      logTheDifference("border diff");
      return true;
   }
}

private boolean checkBorderDiff(Border borderObjA, Border borderObjB) {
    if (borderObjA.getColor() != null || borderObjB.getColor() != null) {
       if (!borderObjA.getColor().equals(borderObjB.getColor())) {
            logIt("border color differing");
            return true;
        }
    }

    if (borderObjA.getDistanceFromText() != borderObjB.getDistanceFromText()) {
        logIt("distance of the border from text or from the page edge in points differing");
        return true;
    }

    if (borderObjA.isVisible() != borderObjB.isVisible()) {
        logIt("border visibility differing");
        return true;
    }

    if (borderObjA.getLineStyle() != borderObjB.getLineStyle()) {
        logIt("line style differing for border");
        return true;
    }

    if (borderObjA.getLineWidth() != borderObjB.getLineWidth()) {
        logIt("border width in points differing");
        return true;
    }

    if (borderObjA.getShadow() != borderObjB.getShadow()) {
        logIt("border shadow differing");
        return true;
    }
}

//And it is going like this.

我的问题是我想避免在方法中使用多个 if 语句。我还想记录与特定差异相对应的消息。

我读过一些类似的 stackoverflow 问题,通过命令模式或 HashMap 解决。但他们不包括比较。

我想重构我的代码以摆脱一系列 if。

【问题讨论】:

标签: java design-patterns optimization refactoring command-pattern


【解决方案1】:

拥有一个由泛型支持的比较器系统。每个比较器也将知道接下来是什么。例如:

interface IComparer<T> {
    boolean areDifferent (T first, T second);
}

class FontComparer implements IComparer<Font> {
    @Override
    public boolean areDifferent(Font first, Font second) {
        // Compare fonts start
        // ..
        // Compare fonts end
        return new BorderComparer().areDifferent(first.getBorder(), second.getBorder());
    }
}


class BorderComparer implements IComparer<Border> {

    @Override
    public boolean areDifferent(Border first, Border second) {
        //Do border comparison alone
        return false;
    }
}

您现在可以设置比较器链,并在比较失败时退出。否则,比较将转到链中的下一个比较器。

客户端代码最终将如下所示:

    Object one = new Object();
    Object two = new Object();
    new ObjectComparer().areDifferent(one, two);

【讨论】:

  • 这里具体怎么登录?
  • @PrakharBansal 将其记录在适当的“areDifferent”方法中。例如; logTheDifference("字体粗体格式不同");将在 FontComparer 的 areDifferent 方法中完成。
  • 但是事情是这样的,一系列if的问题没有解决,因为FontComparer类需要所有的if来比较方法,例如:getBold(),getAllCaps()等
  • 我不完全确定您为什么要再次拆分 FontComparer 中的比较,除非它是 FontComparer 中的一个 真正 长的 if 比较列表。在这种情况下,您可以采用混合方法 - 使用比较器进行高级拆分;在每个比较器中,使用@OldCurmudgeon 给出的枚举解决方案。但是,我必须说,这种细粒度的分解可能会对程序的可读性产生不利影响。
  • 是每个比较器中的比较长列表。是的,因为我担心可读性和可维护性。谢谢。
【解决方案2】:

你考虑过枚举吗?

private enum FontCmp {

    Bold {
                @Override
                boolean cmp(Font a, Font b) {
                    return a.getBold() != b.getBold();
                }
            },
    AllCaps {
                @Override
                boolean cmp(Font a, Font b) {
                    return a.getAllCaps() != b.getAllCaps();
                }
            },
    Border {
                @Override
                boolean cmp(Font a, Font b) {
                    return BorderCmp.compare(a.getBorder(), b.getBorder());
                }
            };

    // Each enum has one of these.
    abstract boolean cmp(Font a, Font b);

    // Compare them all and log any failures.
    static boolean compare(Font a, Font b) {
        for (FontCmp c : FontCmp.values()) {
            if (c.cmp(a, b)) {
                logIt("FontCmp-" + c + " failed");
                return false;
            }
        }
        return true;
    }
}

【讨论】:

  • 不,我没有考虑枚举方法,谢谢,它似乎很好。在每个枚举值中不写入覆盖方法 boolean cmp(Font a, Font b) 的任何方式。
  • @PrakharBansal - 您必须定义如何在某处比较两个Font.Bolds,但是您编写它 - 当然除非您沿着反射路线走,在这种情况下您会遇到两个问题,俗话说。
【解决方案3】:

您也可以按照here 的描述使用反射。还可以按照here

的描述进行内省

【讨论】:

  • 我现在不想使用反射,因为我已经构建了 3k+ loc,只想重构并摆脱 if 的。
  • 那么我认为aquaraga的建议是迄今为止最好的。
【解决方案4】:

从根本上说,您是在尝试进行一系列比较,因此别无选择,只能进行一系列比较。

你可以做的是定义一个接口/枚举/抽象类,它是一个 FieldChecker。该 FieldChecker 将在每个 FieldChecker 中以不同方式实现一个抽象方法:

 String performCheck(Font a, Font b) {
     if (DO CHECK HERE) {
         return "failure message";
     }
     return null;
 }

那么你的检查功能就变成了:

for (FieldChecker fc: fieldCheckers) {
    String res = fc.performCheck(a,b);
    if (res != null) {
       return res;
    }
}
return "All ok";

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    • 2010-11-15
    • 2021-03-18
    • 1970-01-01
    • 1970-01-01
    • 2018-04-04
    相关资源
    最近更新 更多