2014-12-01 2 views
0

Я сталкиваюсь с множеством подобных методов с некоторым повторяющимся кодом в своих проектах. Общая картина кажется выглядеть (извинения за туманный код, лицензирование не позволит мне дать конкретный пример):Показатели эффективности рефакторинга аналогичных методов в схеме стратегии?

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

«doMoreThingsForTypeXPerson» методы могут быть похожи или не похожи, в зависимости от контекста.

Лично я чувствую, что рисунок или зависимость инъекция стратегии может быть использована, чтобы избавиться от подобного кода и устранить необходимость написания нескольких методов каждого типа, поэтому он будет выглядеть следующим образом:

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

Factory pattern - более подходящий образец в этой ситуации. Поскольку ваши Лицы отличаются только типом и некоторыми другими атрибутами. Вы можете создать базовый класс «Личность» и определить тип своего лица в вашем классе PersonFactory. –

ответ

1

Всякий раз, когда вы обмениваетесь кодом ветвления типа (связью операторов if/else или переключателем) для чего-то абстрактного и полиморфного, вы обычно платите несколько более высокую стоимость только с самыми редкими исключениями (например: когда icache хиты становятся важными), возможно, значительно выше, если вы привлечете некоторый поиск в обмен, как Map.

И вы делаете это обычно с учетом расширяемости, чтобы вы могли продлить то, что поддерживает исходный код, без постоянной его модификации (например: избегать постоянного возиться с editPersonBasedOnType) или изменить его как можно больше. Иногда это становится необходимостью, если невозможно продолжить редактирование таких функций до конца времени, например, если поведение должно расширяться третьими лицами, добавляя плагины, расширяющие диапазон поведения.

Итак, независимо от того, поддерживаете ли вы возможность расширения или производительность, но стоит отметить, что здесь обычно используются некоторые издержки производительности микроэффективности. Также стоит отметить, что производительность часто превосходит производительность микроуровня, за исключением самых узких, самых крутых частей вашей кодовой базы, которые появляются в вашем профилировщике.

Так что я бы выбрал любой дизайн, соответствующий вашим потребностям. В вашем примере кода я предполагаю, что он был упрощен по сравнению с оригиналом, и там я бы не одобрял такой маршрут, и только одно место включало возможность 3 типов. Разумные решения являются только умными, когда они фактически уменьшают нагрузку. Но, возможно, ваш исходный код намного шире и становится бременем обслуживания с широкими планами продолжения его распространения и расширения, и если это так, возможно, стоит переработать полиморфный дизайн.

Смежные вопросы