[英]Avoiding code duplication for methods with different return types
I have two builder classes that return a Tree
and a Set
respectively. 我有两个生成器类,分别返回一个
Tree
和一个Set
。 The execution of the second builder is just the execution of the first builder with an extra step and a different return type. 第二个构建器的执行只是第一个构建器的执行,带有额外的步骤和不同的返回类型。 I really don't want to duplicate the same steps in two different classes, because if there is a change in the
Tree
-building process, I have to change code in two classes. 我真的不想在两个不同的类中重复相同的步骤,因为如果在
Tree
构建过程中进行了更改,则必须在两个类中更改代码。 Here are the two builders: 这是两个构建器:
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;
}
}
The second builder uses one more dependency and returns a Set
instead of a Tree
: 第二个构建器使用另一个依赖项,并返回
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;
}
}
I am looking for a way to avoid the duplication. 我正在寻找一种避免重复的方法。 Any suggestions?
有什么建议么?
FreePortsBuilder
is doing two things at the same time: FreePortsBuilder
同时执行两项操作:
Tree
: as you know, this is identical to what TreeBuilder
does. Tree
:如您所知,这与TreeBuilder
作用相同。 Set<PortNameAndLabel>
, where each PortNameAndLabel
appears to be associated with a node or child (which is itself a Tree
) in the final Tree
. Set<PortNameAndLabel>
,其中每个PortNameAndLabel
似乎与最终Tree
的节点或子代(本身就是Tree
)相关联。 Instead of doing the above two things simultaneously, do them sequentially. 与其同时执行上述两件事,不如依次执行它们。 That is, in
FreePortsBuilder
, first use TreeBuilder
to build the Tree
, then traverse this Tree
to construct the Set<PortNameAndLabel>
. 也就是说,在
FreePortsBuilder
, 首先使用TreeBuilder
来构建Tree
, 然后遍历此Tree
来构建Set<PortNameAndLabel>
。 One way to do that is the following (I assume that your Tree
class has a method like getChildren()
that returns a List<Tree<EquipmentDetails>>
). 一种实现方法如下(我假设您的
Tree
类具有类似getChildren()
的方法,该方法返回List<Tree<EquipmentDetails>>
)。
First, allow a client to obtain a TreeBuilder
's NodeHelper
by adding a getter: 首先,允许客户端通过添加getter获得
TreeBuilder
的NodeHelper
:
public class TreeBuilder {
private NodeHelper nodeHelper;
public NodeHelper getNodeHelper() {
return this.nodeHelper;
}
...
}
Then, inject a TreeBuilder
instead of a NodeHelper
into FreePortsBuilder
( FreePortsBuilder
can use the NodeHelper
that is in the TreeBuilder
, because of the getter that we just added): 然后,注入
TreeBuilder
代替NodeHelper
到FreePortsBuilder
( 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;
}
}
Now, FreePortsBuilder
can truly make use of the TreeBuilder
implementation, and the code duplication is removed. 现在,
FreePortsBuilder
可以真正利用TreeBuilder
实现,并且删除了重复的代码。
You can use Strategy design pattern or Template Method here. 您可以在此处使用策略设计模式或模板方法 。 You have an algorithm here where only certain steps change (collectFreePorts & buildTree).
您这里有一个算法,其中仅某些步骤会发生变化(collectFreePorts和buildTree)。
If you cannot use inheritance, you can use a similar solution to this: https://softwareengineering.stackexchange.com/questions/187872/template-method-within-one-class-without-subclasses-or-inheritance 如果您不能使用继承,则可以使用类似的解决方案: https : //softwareengineering.stackexchange.com/questions/187872/template-method-within-one-class-without-subclasses-or-inheritance
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.