2013-02-20 4 views
0

У меня есть необходимость в пересмотре методов бизнес-правил при сохранении всех предыдущих версий. Класс, в котором они содержатся, будет одинаковым, но содержание каждого метода будет другим. Я бы предпочел, чтобы у них была одна и та же подпись метода. Вызывающий будет знать версию, которую он хотел бы выполнить. Я также предпочел бы не иметь _vX в имени метода (как пример ниже). Есть лучший способ сделать это? Что-то вроде аннотации по каждому методу было бы неплохо, но в кратком тесте, который не казался возможным сделать метод достаточно уникальным.Как можно управлять версией java?

public class SomeSpecificRule { 
    public Response processRule_v1() { 
    } 
    public Response processRule_v2() { 
    } 
} 

Редактировать: Причина различных методов является то, что логика, содержащаяся в методах, вероятно, будет эффективной в разное время (первичный сценарий), но мы должны быть в состоянии запустить любую версию в любой момент времени (вторичные). method_v1 используется для дат x1-x2, а метод_v2 из дат x2-x3 будет общим. Тем не менее, «какую версию мы должны использовать» заданные даты и другую логику критериев, я хочу сохранить отдельно, чтобы упростить создание этих классов и дополнительных методов для других разработчиков.

ответ

7

Без каких-либо других спецификаций, это звучит, как вы хотите использовать интерфейс:

interface Rules { 
    Response processRule(); 
} 

class Rules_v1 implements Rules { 
    public Response processRule() { ... } 
} 

class Rules_v2 implements Rules { 
    public Response processRule() { ... } 
} 
+0

Единственные негативы, которые я вижу с этим, - это количество файлов (~ 50 правил с 1-5 версиями каждый, что может быть приемлемым) и использование рефлексии или другого класса фабрики для создания конкретной версии (в отличие от просто передать номер версии и использовать переключатель). – bobtheowl2

+0

@ bobtheowl2: Я не уверен, как вы могли избежать этой сложности. В какой-то момент, где-то в вашем коде, вам как-то придется ссылаться на правильную комбинацию версии и метода! –

1

Это не возможно версии метода. Одна подпись может появляться только один раз. У вас могут быть разные классы, которые имеют один и тот же метод, и извлекают их через фабрику или какой-либо другой метод, но вы не можете делать то, что вы просите.

0

Или вы могли бы сделать версионности внутренне:

processRule(..., int Version = 0) 
{ 
switch (Version) 
    //etc 
} 

Если вы по умолчанию Version == 0, как "текущей версии", это может быть относительно практической?

Мой аргумент заключается в том, что то, что вы называете «версиями бизнес-логики», на самом деле является самой бизнес-логикой, потому что вы явно используете несколько версий , потому что ваш бизнес требует его.

1

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

Я думаю, что простой подход ООП (как предложено в других ответах) может быть более удобным.

+1

Я был сожжен в прошлом, играя с этой черной магией. – bobtheowl2

0

В идеале вам никогда не придется этого делать, но если вам нужно поддерживать методы, которые сопоставляются с элементами в каком-то версионном проводном интерфейсе, то представляйте версии как значения на языке и используйте метод батута, чтобы поддерживать простой API ,

enum Version { 
    V1, 
    V2, 
    V3, 
    ; 
} 

public class ClassWithVersionedMethod { 
    // Protected to allow overriding while preventing clients from calling 
    // versioned methods explicitly, and to minimize clutter in the javadoc and 
    // IDE-autocomplete menus. 
    protected T methodV1(...) { ... } 
    protected T methodV2(...) { ... } 
    protected T methodV3(...) { ... } 

    // Final to prevent overriding of unversioned method by accident. 
    public final T method(Version v, ...) { 
    switch (v) { 
     case V1: return methodV1(...); 
     case V2: return methodV2(...); 
     case V3: return methodV3(...); 
    } 
    // Throw outside switch so that we get a compiler warning when 
    // someone adds a member to Version. 
    throw new AssertionError("Unsupported version " + v); 
    } 
} 
0

Это дань уважения ответам Kajetan Abt, но их обновление.

public void processRule(int version) 
     { 
     switch (Version){ 
      case 1: 
      executeRule1(); 
      break; 
      case 2: 
      executeRule2(); 
      break; 
     } 

    } 

    //executeRule1(), executeRule2() functions declarations here 

Я думаю, что это лучше, чем создание новых классов, потому что вы пытаетесь сохранить все предыдущие версии методов.

+0

У вас есть хорошая идея сохранить все версии логики в одном месте и эффективно минимизировать количество файлов. – bobtheowl2

0

В основном, что сказано в другом ответе: Используйте интерфейс.

public interface Car { 
    public void start(); 
    public void drive(); 
} 

Как применять:, чтобы полностью сохранить версию беспорядок от кода, создать отдельную реализацию этого интерфейса, в версии.

public class CarV1 implements Car{ 
    public void drive(){} 
    public void start(){} 
} 

public class CarV2 extends CarV1{ 
    @Override 
    public void drive(){//--extra--} 
} 

public class CarNewV3 implements Car{ 
    public void drive(){//--new--} 
    public void start(){//--new--} 
} 

Вы можете создавать полные классы реализации с нуля или распространять предыдущие версии для добавления/переопределения некоторых функций.

Наконец, чтобы телеграфировать все это вместе, то есть, чтобы служить соответствующие версии, вы можете использовать: классы

Factory, они могут обеспечить реализации для конкретной версии. Этот класс может проверить некоторые параметры и выбрать конкретную версию.

public class CarFactory(){ 
    public static Car newCar(){ 
    if(year >= 2013){ 
     return new CarNewV3(); 
    }else if (year >= 2000){ 
     return new CarV2(); 
    }else{ 
     retrun new CarV1(); 
    } 
    } 
} 

Или использовать некоторые DI рамки, таким образом, вы пишете небольшой дополнительный набор вверх класс (модуль), где вы выясняете лучшие реализации для использования во время выполнения.

+0

Есть ли способ обойти именование, не имея _v1 и _v2 в реализующих классах? – bobtheowl2

+0

@ bobtheowl2 по крайней мере, классы реализации должны иметь разные имена. Вы не можете получить доступ к другой логике, без уникального имени, ссылающегося на нее. Методы будут иметь одно и то же имя, которое вы объявляете в интерфейсе. –

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