将类似方法重构为策略模式的性能成本?

时间:2014-12-01 21:44:18

标签: java performance oop refactoring

我发现自己面临很多类似的方法,在我的项目中有一些重复的代码。一般模式似乎看起来像(对模糊代码道歉,许可获胜并且让我提供一个具体的例子):

 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}
}

您会使用第一种方法还是重构方法?或者这种一般情况有更好的方法吗?是否需要关注实例化策略对象的成本?

1 个答案:

答案 0 :(得分:1)

每当你为抽象和多态的东西交换具体类型的分支代码(一堆if / else语句或一个开关)时,你通常会付出更高的成本而只有最稀有的例外(例如:当icache命中时变得很重要,如果你像Map那样参与一些查询,那么可能要高得多。

这样做通常考虑到可扩展性,以便您可以扩展原始代码所支持的内容而无需不断修改它(例如:避免不断摆弄editPersonBasedOnType)或修改它。有时,如果在时间结束之前不可能继续编辑这些函数,那么它就变得必不可少了,就像第三方添加插件来扩展行为范围时,行为应该是可扩展的。

因此,您是否赞成可扩展性或性能取决于您,但值得注意的是,这里的微效率排序通常会有一些性能开销。值得注意的是,除了在您的探查器中显示的代码库中最紧密,最环节的部分之外,生产力通常胜过微观级别的性能。

所以我会选择适合您需求的设计。在你的示例代码中,我假设它已经简化了原始版本,并且我不赞成走这样一条路线,只有一个地方可以切换3种类型的可能性。更智能的解决方案只有在真正减轻负担时才是智能的。但是,您的原始代码可能会更广泛并且成为维护负担,并有广泛的计划继续扩展和扩展它,如果是这样,可能值得重构多态设计。