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

时间:2017-10-10 04:22:08

标签: java oop design-patterns

我有两个构建器类,分别返回TreeSet。第二个构建器的执行只是第一个构建器的执行,具有额外的步骤和不同的返回类型。我真的不想在两个不同的类中复制相同的步骤,因为如果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;
    }
}

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

2 个答案:

答案 0 :(得分:2)

FreePortsBuilder同时做两件事:

  1. 构建Tree:如您所知,这与TreeBuilder的内容相同。
  2. 构建Set<PortNameAndLabel>,其中每个PortNameAndLabel似乎与最终Tree中的节点或子项(本身为Tree)相关联。
  3. 不是同时执行上述两项操作,而是按顺序执行。也就是说,在FreePortsBuilder首先使用TreeBuilder来构建Tree然后遍历此Tree来构建Set<PortNameAndLabel>。一种方法是执行此操作(我假设您的Tree类有一个方法,如getChildren(),返回List<Tree<EquipmentDetails>>)。

    首先,允许客户通过添加getter获取TreeBuilder的{​​{1}}:

    NodeHelper

    然后,将public class TreeBuilder { private NodeHelper nodeHelper; public NodeHelper getNodeHelper() { return this.nodeHelper; } ... } 而不是TreeBuilder注入NodeHelperFreePortsBuilder,可以使用FreePortsBuilder中的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实现,并删除代码重复。

答案 1 :(得分:0)

您可以在此处使用Strategy design patternTemplate Method。你有一个算法,只有某些步骤改变(collectFreePorts&amp; buildTree)。

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