我有两个构建器类,分别返回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;
}
}
我正在寻找避免重复的方法。有什么建议吗?
答案 0 :(得分:2)
FreePortsBuilder
同时做两件事:
Tree
:如您所知,这与TreeBuilder
的内容相同。Set<PortNameAndLabel>
,其中每个PortNameAndLabel
似乎与最终Tree
中的节点或子项(本身为Tree
)相关联。不是同时执行上述两项操作,而是按顺序执行。也就是说,在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
注入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;
}
}
可以真正使用FreePortsBuilder
实现,并删除代码重复。
答案 1 :(得分:0)
您可以在此处使用Strategy design pattern或Template Method。你有一个算法,只有某些步骤改变(collectFreePorts&amp; buildTree)。
如果您无法使用继承,则可以使用类似的解决方案:https://softwareengineering.stackexchange.com/questions/187872/template-method-within-one-class-without-subclasses-or-inheritance