代码之家  ›  专栏  ›  技术社区  ›  kane77

如何正确地重构这个?

  •  2
  • kane77  · 技术社区  · 15 年前

    我很难找到正确重构此代码的方法,以便尽可能少地重复代码,我有以下几种方法(伪代码):

    public List<Something> parseSomething(Node n){
      List<Something> somethings = new ArrayList<Something>();
      initialize();
      sameCodeInBothClasses();
      List<Node> nodes = getChildrenByName(n, "somename");
      for(Node n:nodes){
        method();
        actionA();
        somethings.add(new Something(actionB());
      }
      return somethings;
    }
    

    方法 sameCodeInBothClasses() 在所有类中都是相同的,但在for循环中,它的不同之处在于 actionA() 它还向不同类型的列表中添加了一个元素。

    我应该对循环内的不同部分使用策略模式吗?

    返回值(列表的类型不同)如何,方法是否应该只返回 List<Object> 然后我会选合适的类型?我应该传递要作为参数返回的类吗?

    4 回复  |  直到 15 年前
        1
  •  1
  •   Community CDub    8 年前

    适用的设计模式是 Template Method 而不是战略。

    对于不同类型的项目,我会尝试进行泛型化 parseSomething 首先,像这样:

    public <T> List<T> parseSomething(Node n){
      List<T> somethings = new ArrayList<T>();
      initialize();
      sameCodeInBothClasses();
      List<Node> nodes = getChildrenByName(n, "somename");
      for(Node n:nodes){
        method();
        actionA();
        somethings.add(new T(actionB());
      }
      return somethings;
    }
    

    不过,这可能不会马上对你起作用。可能需要将泛型参数移动到类级别。

    返回 List<Object> 将不起作用,因为泛型集合是 不变量 为了 任何两种不同的类型 Type1 Type2 ,请 List<Type1> 既不是子类型也不是 超类型 List<Type2> (即使 1型 2型 是相关的,即一个是另一个的子类型!)见 an earlier answer of mine 有关此的详细信息。

    因此,如果所有其他方法都失败了,那么快速而肮脏的解决方案实际上将使用非通用的 List .

        2
  •  1
  •   Tomislav Nakic-Alfirevic    15 年前

    如果你这样写:

    public List<T> parseGeneric(Node n) {
      List<T> result = new ArrayList<T>();
      initialize();
      sameCodeInBothClasses();
      List<Node> nodes = getChildrenByName(n, "somename");
      for(Node n:nodes){
        method();
        actionA();
        result.add(new T(actionB()));
      }
      return result;
    }
    

    并将其调用为

    List<Something> somethings = parseGeneric(aSomething);
    

    很难说,在没有可用定义的情况下,有了这些其他的方法,但是我相信你应该能够摆脱上面的一些东西。

        3
  •  1
  •   Stephen C    15 年前

    我的第一个想法是申报 parseSomething 在抽象基类中,对于声明为 abstract 并在子类中实现。创建一个 Something 需要将实例转换为工厂方法。

    问题是 副处事 需要返回概念上不同的类型;例如 List<Something> 对战 List<SomethingElse> .一种方法是识别一个公共的父类型并使返回类型 List<? extends SomeSuper> . 另一种方法是 parseXxx 在每个叶类中具有所需签名的方法,并将它们委托给 protected List<? extends SomeSuper> doParse(...) 基类中的方法。

        4
  •  0
  •   Stuart Sierra    15 年前

    我将为方法actiona和actionb创建一个操作接口。然后一个解析器类用一个方法解析:

    public List parseSomething(Node n, Action a) {
      List something = new ArrayList();
      initialize();
      samecode();
      List<Node> nodes = getChildrenByName(n, "name");
      for(Node n: nodes) {
          a.actionA();
          somethings.add(new Something(a.actionB()));
      }
      return somethings;
    }