我很难找到正确重构此代码的方法,以便尽可能少的重复代码,我有几个像这样的方法(伪代码):
public List<Something> parseSomething(Node n){
List<Something> somethings = new ArrayList<Something>();
initialize();
sameCodeInBothClasses();
List<Node> nodes = getChildrenByName(n, "somename");
for(Node n:nodes){
method();
actionA();
somethings.add(new Something(actionB());
}
return somethings;
}
方法sameCodeInBothClasses()
在所有类中都是相同的,但它不同的地方是循环actionA()
的内容,它还为不同类型的List添加了一个元素。
我应该在循环内部的不同部分使用策略模式吗?
返回值怎么样(列表的类型不同),如果方法只返回List<Object>
,那么我会转换为适当的类型?我应该通过我想要作为参数返回的类吗?
答案 0 :(得分:1)
适用的设计模式是Template Method,而不是策略。
关于不同类型的项目,我会首先尝试对parseSomething
进行泛化,如下所示:
public <T> List<T> parseSomething(Node n){
List<T> somethings = new ArrayList<T>();
initialize();
sameCodeInBothClasses();
List<Node> nodes = getChildrenByName(n, "somename");
for(Node n:nodes){
method();
actionA();
somethings.add(new T(actionB());
}
return somethings;
}
但这可能不适合你。您可能需要将泛型参数移动到类级别。
返回List<Object>
将无效,因为通用集合不变:for
任何两种不同类型Type1
和Type2
,List<Type1>
既不是子类型也不是
List<Type2>
的超类型(即使Type1
和Type2
相关,即一个是另一个的子类型!)。有关详细信息,请参阅an earlier answer of mine。
因此,如果所有其他方法都失败了,快速而肮脏的解决方案确实会使用非通用的List
。
答案 1 :(得分:1)
如果你这样写:
public List<T> parseGeneric(Node n) {
List<T> result = new ArrayList<T>();
initialize();
sameCodeInBothClasses();
List<Node> nodes = getChildrenByName(n, "somename");
for(Node n:nodes){
method();
actionA();
result.add(new T(actionB()));
}
return result;
}
并将其作为
调用List<Something> somethings = parseGeneric(aSomething);
如果没有可用的定义,很难说所有这些其他方法,但我相信你应该能够摆脱上述类似的事情。
答案 2 :(得分:1)
我的第一个想法是在一个抽象基类中声明parseSomething
,每个类声明为abstract
并在子类中实现的方法不同。创建Something
实例的内联代码需要转换为工厂方法。
问题是parseSomething
的签名需要返回不同类型的概念;例如List<Something>
与List<SomethingElse>
。一种方法是识别常见的超类型并返回类型List<? extends SomeSuper>
。另一种方法是在每个叶类中创建具有所需签名的parseXxx
方法,并将它们委托给基类中的protected List<? extends SomeSuper> doParse(...)
方法。
答案 3 :(得分:0)
我为方法actionA和actionB创建一个Action接口。然后是一个带有方法parseSomething的Parser类:
public List parseSomething(Node n, Action a) {
List something = new ArrayList();
initialize();
samecode();
List<Node> nodes = getChildrenByName(n, "name");
for(Node n: nodes) {
a.actionA();
somethings.add(new Something(a.actionB()));
}
return somethings;
}