背景
我在代码中遇到了很多方法我负责重构,遵循以下一般模式:
在代码中它看起来像这样:
public Composite trim(Composite composite, List<Child> removed){
for (Child child : composite.getChildren()){
if (criterion(child)){
composite.remove(child);
removed.add(child);
}
}
}
这里有许多代码气味,但我想解决的是如何将其重构为不可变代码,因此不会写入输出参数。
可能但不那么优雅的解决方案
public Map<String, Object> trim(Composite composite){
final List<Child> removableChildren = filter(composite);
final Composite trimmed = copyCompositeWithoutChildren(composite, removableChildren);
return wrapInMap(removableChildren, trimmed);
}
问题
有没有更简洁的方法来实现这一点,例如,在groovy或Java 8中使用诸如收集或拼接之类的函数式编程方法可能会在Java pre-8中提供更好的,尽管更详细的方法?任何一种语言的例子都将受到高度赞赏。
修改
第二种可能的解决方案
受Steinar's answer的启发:使用策略模式。
public interface FilterStrategy {
List<Child> filter(List<Child> children);
}
public interface RemovalResponseStrategy {
void respond(List<Child> removedChildren);
}
public class CompositeTrimmer {
private final FilterStrategy filterStrategy;
private final RemovalResponseStrategy removalResponseStrategy;
public Composite trim(final Composite composite){
final List<Child> removableChildren =
filterStrategy.filter(composite.getChildren());
final Composite trimmed =
copyCompositeWithoutChildren(composite, removableChildren);
removalResponseStrategy.respond(removableChildren);
return trimmed;
}
}
答案 0 :(得分:1)
你没有说你有什么样的自由来改变Composite
类或者哪种方法
已有。所以我刚刚做了些什么。它可能会被改装成你所拥有的
很容易。
更多的常规解决方案是这样的:
def trim(Composite composite, Closure removeCriterion) {
List<Child> removedChildren = composite.children.findAll(removeCriterion)
List<Child> remainingChildren = composite.children - removedChildren
Composite filteredComposite = new Composite(children: remainingChildren)
[filteredComposite, removedChildren]
}
您不需要将标准指定为参数,但我有点喜欢它。使代码更多 柔性的。
基本上,首先找到要移除的子项,然后与剩余的子项一起创建一个新的复合。 最后返回两个输出的列表。由于groovy支持列表中的多个赋值,所以 返回多个输出的简单方法。
使用Composite
和Child
的虚拟实现测试了解决方案。
用法和测试:
def test() {
Composite composite = new Composite(children: [
new Child(name: 'Angus'),
new Child(name: 'Steinar'),
new Child(name: 'Erik'),
new Child(name: 'William'),
])
def (Composite filteredComposite, List<Child> removedChildren) =
trim(composite) {
Child child -> child.name > 'H'
}
assert filteredComposite.children == [new Child(name: 'Angus'), new Child(name: 'Erik')]
assert removedChildren == [new Child(name: 'Steinar'), new Child(name: 'William')]
}
@ToString(includePackage = false)
@EqualsAndHashCode
class Child {
String name
}
@ToString(includePackage = false)
@EqualsAndHashCode
class Composite {
List<Child> children
}