我发现自己面临很多类似的方法,在我的项目中有一些重复的代码。一般模式似乎看起来像(对模糊代码道歉,许可获胜并且让我提供一个具体的例子):
public void modifyType1Person() {
Map<String, ?> parameters = new HashMap<>();
parameters.put("type", "type1");
parameters.put("stringArgument", "some name");
editPersonBasedOnType(parameters);
}
public void modifyType2Person() {
Map<String, ?> parameters = new HashMap<>();
parameters.put("type", "type2");
editPersonBasedOnType(parameters);
}
public void modifyDefaultTypePerson() {
Map<String, ?> parameters = new HashMap<>();
parameters.put("type", "otherType");
parameters.put("booleanArgument", true);
editPersonBasedOnType(parameters);
}
public void editPersonBasedOnType(Map<String, ?> parameters) {
// assume some stuff is done
switch (parameters.get("type")) {
case "type1":
editType1Person(parameters.get("stringArgument"));
case "type2":
editType2Person();
default:
editOtherType(parameters.get("type"), parameters.get("booleanArgument"));
}
// assume more stuff is done
}
private void editType1Person(String stringArg) {
Person person = PersonService.getPerson(stringArg);
person.edit();
doMoreThingsForType1Person(person);
}
private void editType2Person() {
Person person = PersonService.getPerson(HARDCODED_NAME);
person.edit();
doMoreThingsForType2Person(person);
}
private void editOtherType( String type, boolean boolArg ) {
Person person = PersonService.getPerson(HARDCODED_NAME);
person.edit()
doMoreThingsForDefaultTypePerson(person)
}
&#34; doMoreThingsForTypeXPerson&#34;根据上下文,方法可以相似或不相似。
就个人而言,我觉得策略模式或依赖注入可以用来摆脱类似的代码,并且不需要为每种类型编写多个方法,所以它看起来像:
public void modifyType1Person() {
editPersonBasedOnType(new Type1Strategy("some name"));
}
public void modifyType2Person() {
editPersonBasedOnType(new Type2Strategy());
}
public void modifyDefaultTypePerson() {
editPersonBasedOnType(new DefaultTypeStrategy("other type", true));
}
public void editPersonBasedOnType(TypeStrategy typeStrategy) {
// assume some stuff is done
typeStrategy.doProcedure();
// assume more stuff is done
}
public interface TypeStrategy {
public void doProcedure()
}
public class Type1Strategy {
private String stringArgument;
public Type1Strategy(String stringArgument) {
this.stringArgument = stringArgument;
}
public void doProcedure() {
// editType1Person method
}
private void doMoreThingsForType1Person() {//implementation}
}
public class Type2Strategy {
public void doProcedure() {
// editType2Person method
}
private void doMoreThingsForType2Person() {//implementation}
}
public class DefaultTypeStrategy {
private String type;
private boolean boolArg;
public DefaultTypeStrategy(String type, boolean boolArg) {
this.type = type;
this.boolArg = boolArg;
}
public void doProcedure() {
// editOtherType code
}
private void doMoreThingsForDefaultTypePerson() {//implementation}
}
您会使用第一种方法还是重构方法?或者这种一般情况有更好的方法吗?是否需要关注实例化策略对象的成本?
答案 0 :(得分:1)
每当你为抽象和多态的东西交换具体类型的分支代码(一堆if / else语句或一个开关)时,你通常会付出更高的成本而只有最稀有的例外(例如:当icache命中时变得很重要,如果你像Map
那样参与一些查询,那么可能要高得多。
这样做通常考虑到可扩展性,以便您可以扩展原始代码所支持的内容而无需不断修改它(例如:避免不断摆弄editPersonBasedOnType
)或修改它。有时,如果在时间结束之前不可能继续编辑这些函数,那么它就变得必不可少了,就像第三方添加插件来扩展行为范围时,行为应该是可扩展的。
因此,您是否赞成可扩展性或性能取决于您,但值得注意的是,这里的微效率排序通常会有一些性能开销。值得注意的是,除了在您的探查器中显示的代码库中最紧密,最环节的部分之外,生产力通常胜过微观级别的性能。
所以我会选择适合您需求的设计。在你的示例代码中,我假设它已经简化了原始版本,并且我不赞成走这样一条路线,只有一个地方可以切换3种类型的可能性。更智能的解决方案只有在真正减轻负担时才是智能的。但是,您的原始代码可能会更广泛并且成为维护负担,并有广泛的计划继续扩展和扩展它,如果是这样,可能值得重构多态设计。