Как избежать отражения, используя перечисления - PullRequest
0 голосов
/ 14 июня 2019

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

Итак, у меня есть интерфейс для поиска во внешних системах:

public interface ReferenceController {

  public Map<String, ReferenceElement> searchElements(String searchField, List<String> searchItems, SystemStage systemStage) throws Exception;

  public String getStateMapping(String value);

  public Boolean isAvailable(SystemStage systemStage) throws Exception;
}

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

Поэтому часть, где я использовал отражение, была

public static void performSingleSearch(ReferenceSystem referenceSystem, String searchField, List<String> searchValues, SystemStage systemStage) throws Exception {

    if(!isAvailable(referenceSystem, systemStage)) return;
    Map<String, ReferenceElement> result = new HashMap<>();
    try {
        Class<?> classTemp = Class.forName(referenceSystem.getClassname());
        Method method = classTemp.getMethod("searchElements", String.class , List.class, SystemStage.class);
        result = (Map<String, ReferenceElement>) method.invoke(classTemp.newInstance(), searchField, searchValues, systemStage);
    } catch (Exception e) { 
        return;
    }
    if(result != null) orderResults(result, referenceSystem);
}

В ENUM есть функция getClassname, которая отвечает с помощью fqcn.Enum выглядит следующим образом:

public enum ReferenceSystem {
    UCMDB    (refSystems.ucmdb.UcmdbFunctions.class),
    PROIPS   (refSystems.proips.ProIPSFunctions.class),
    KV       (refSystems.kv.KvFunctions.class),
    FISERVICE(refSystems.fiservice.FiServiceFunctions.class),
    COMMAND  (refSystems.command.CommandFunctions.class),
    FII          (refSystems.fii.FiiFunctions.class);

    private Class<?> clazz;

    private ReferenceSystem(Class<?> controllerClass) {
        this.clazz = controllerClass;
    }

    public String displayName() {
        ResourceBundle bundle = ResourceBundle.getBundle("EnumI18n", Locale.GERMAN);
        return bundle.getString(toString()); 
    }

    public String localizedDisplayName(Locale locale) {
        ResourceBundle bundle = ResourceBundle.getBundle("EnumI18n", locale);
        return bundle.getString(toString()); 
    }

    public Class<?> getClassname() { return clazz; }
}

Я уже изменил его в соответствии с ответом @jhamon.

Но я получаю ошибку, когда пытаюсь

classTemp.newInstance().searchElemets(...)

Поскольку он не знает о searchElemts ().

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

1 Ответ

0 голосов
/ 14 июня 2019

Кажется, у всех ваших поисковых систем есть общий метод searchElements, и он определен в интерфейсе

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

public interface ReferenceController {

    public Map<String, ReferenceElement> searchElements(String searchField, List<String> searchItems, SystemStage systemStage) throws Exception;

    public String getStateMapping(String value);

    public Boolean isAvailable(SystemStage systemStage) throws Exception;
}

Вместо того, чтобы хранить имя класса как String в Enum, сохраните .class -> больше нет отражения, чтобы найти класс.

public static void performSingleSearch(ReferenceSystem referenceSystem, String searchField, List<String> searchValues, SystemStage systemStage) throws Exception {

    if(!isAvailable(referenceSystem, systemStage)) return;
    Map<String, ReferenceElement> result = new HashMap<>();
    try {
        Class<?> classTemp = referenceSystem.getClazz();
        result = ((ReferenceController) classTemp.newInstance()).searchElements(searchField, searchValues, systemStage);
    } catch (Exception e) { 
        return;
    }
    if(result != null) orderResults(result, referenceSystem);
}
...