簡體   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