繁体   English   中英

避免对具有不同返回类型的方法进行代码重复

[英]Avoiding code duplication for methods with different return types

我有两个生成器类,分别返回一个Tree和一个Set 第二个构建器的执行只是第一个构建器的执行,带有额外的步骤和不同的返回类型。 我真的不想在两个不同的类中重复相同的步骤,因为如果在Tree构建过程中进行了更改,则必须在两个类中更改代码。 这是两个构建器:

public class TreeBuilder {

    private NodeHelper nodeHelper;

    public TreeBuilder(NodeHelper nodeHelper) {
        this.nodeHelper = nodeHelper;
    }

    public Tree<EquipmentDetails> buildTree() {

        Tree<EquipmentDetails> tree = new Tree<>(nodeHelper.getEquipmentDetails(nodeHelper.getModelName()));

        return buildTree(tree);
    }

    private Tree<EquipmentDetails> buildTree(Tree<EquipmentDetails> parentTree) {

        Map<String, NativeSlotDisplayLabel> childSubTypeMap = nodeHelper.getChildSubTypeMap(parentTree);

        if (CommonUtils.nullOrEmpty(childSubTypeMap))
            return parentTree;

        for (String holderCommonName : childSubTypeMap.keySet()) {

            NativeSlotDisplayLabel nativeSlotDisplayLabel = childSubTypeMap.get(holderCommonName);

            EquipmentDetails equipmentDetails = nodeHelper.constructEqptDetails(holderCommonName, nativeSlotDisplayLabel, parentTree);

            Tree<EquipmentDetails> childTree = new Tree<>(equipmentDetails);

            parentTree.addChild(childTree);

            String equipmentCommonName = equipmentDetails.getModelEquipType();

            if (equipmentCommonName == null)
                continue;

            buildTree(childTree);
        }

        return parentTree;
    }
}

第二个构建器使用另一个依赖项,并返回Set而不是Tree

public class FreePortsBuilder {

    private NodeHelper nodeHelper;

    private PortLabelGenerator portLabelGenerator;

    public FreePortsBuilder(NodeHelper nodeHelper, PortLabelGenerator portLabelGenerator) {
        this.nodeHelper = nodeHelper;
        this.portLabelGenerator = portLabelGenerator;
    }

    public Set<PortNameAndLabel> collectFreePorts(){

        Tree<EquipmentDetails> tree = new Tree<>(nodeHelper.getEquipmentDetails(nodeHelper.getModelName()));

        Set<PortNameAndLabel> portNameAndLabels = new HashSet<>();

        return collectFreePorts(tree, portNameAndLabels);
    }

    private Set<PortNameAndLabel> collectFreePorts(Tree<EquipmentDetails> parentTree, Set<PortNameAndLabel> portNameAndLabels) {

        Map<String, NativeSlotDisplayLabel> childSubTypeMap = nodeHelper.getChildSubTypeMap(parentTree);

        if (CommonUtils.nullOrEmpty(childSubTypeMap))
            return portNameAndLabels;

        Set<PortNameAndLabel> generatedPortNameAndLabel = portLabelGenerator.getPortNameAndLabel(childSubTypeMap, parentTree.getUserObject());

        portNameAndLabels.addAll(generatedPortNameAndLabel);

        for (String holderCommonName : childSubTypeMap.keySet()) {

            NativeSlotDisplayLabel nativeSlotDisplayLabel = childSubTypeMap.get(holderCommonName);

            EquipmentDetails equipmentDetails = nodeHelper.constructEqptDetails(holderCommonName, nativeSlotDisplayLabel, parentTree);

            Tree<EquipmentDetails> childTree = new Tree<>(equipmentDetails);

            parentTree.addChild(childTree);

            String equipmentCommonName = equipmentDetails.getModelEquipType();

            if (equipmentCommonName == null)
                continue;

            collectFreePorts(childTree, portNameAndLabels);
        }

        return portNameAndLabels;
    }
}

我正在寻找一种避免重复的方法。 有什么建议么?

FreePortsBuilder同时执行两项操作:

  1. 构建Tree :如您所知,这与TreeBuilder作用相同。
  2. 构建一个Set<PortNameAndLabel> ,其中每个PortNameAndLabel似乎与最终Tree的节点或子代(本身就是Tree )相关联。

与其同时执行上述两件事,不如依次执行它们。 也就是说,在FreePortsBuilder首先使用TreeBuilder来构建Tree然后遍历此Tree来构建Set<PortNameAndLabel> 一种实现方法如下(我假设您的Tree类具有类似getChildren()的方法,该方法返回List<Tree<EquipmentDetails>> )。

首先,允许客户端通过添加getter获得TreeBuilderNodeHelper

public class TreeBuilder {
  private NodeHelper nodeHelper;

  public NodeHelper getNodeHelper() {
    return this.nodeHelper;
  }

  ...
}

然后,注入TreeBuilder代替NodeHelperFreePortsBuilderFreePortsBuilder可以使用NodeHelper是在TreeBuilder ,因为我们刚才添加的吸气剂):

public class FreePortsBuilder {
  private TreeBuilder treeBuilder;
  private PortLabelGenerator portLabelGenerator;

  public FreePortsBuilder(TreeBuilder treeBuilder, PortLabelGenerator portLabelGenerator) {
    this.treeBuilder = treeBuilder;
    this.portLabelGenerator = portLabelGenerator;
  }

  public Set<PortNameAndLabel> collectFreePorts() {
    Tree<EquipmentDetails> tree = treeBuilder.buildTree();
    return collectFreePorts(tree);
  }

  private Set<PortNameAndLabel> collectFreePorts(Tree<EquipmentDetails> tree) {
    Set<PortNameAndLabel> portNameAndLabels = new HashSet<>();

    for (Tree<EquipmentDetails> child : tree.getChildren()) {
      Map<String, NativeSlotDisplayLabel> childSubTypeMap =
          treeBuilder.getNodeHelper().getChildSubTypeMap(child);

      if (CommonUtils.nullOrEmpty(childSubTypeMap))
        continue;

      Set<PortNameAndLabel> generatedPortNameAndLabel =
          portLabelGenerator.getPortNameAndLabel(childSubTypeMap, child.getUserObject());

      portNameAndLabels.addAll(generatedPortNameAndLabel);
    }

    return portNameAndLabels;
  }
}

现在, FreePortsBuilder可以真正利用TreeBuilder实现,并且删除了重复的代码。

您可以在此处使用策略设计模式模板方法 您这里有一个算法,其中仅某些步骤会发生变化(collectFreePorts和buildTree)。

如果您不能使用继承,则可以使用类似的解决方案: https : //softwareengineering.stackexchange.com/questions/187872/template-method-within-one-class-without-subclasses-or-inheritance

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM