Статическое предоставление метаданных для класса в принудительном порядке

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

Для начала рассмотрим следующие классы.

public abstract class Invokable {
    private String name;

    protected Invokable(String name) { ... }

    public String getName() { ... }

    public abstract void invoke();
}

public class PrintInvokable extends Invokable {
    public PrintInvokable() {
        super("print");
    }

    @Override
    public void invoke() { ... }
}

Другой класс, InvokerDispatcher, обрабатывает события из приложения для обмена сообщениями и вызывает Invokable#invoke для экземпляра соответствующей реализации на основе поля name. Все это делается рефлексивно, чтобы иметь возможность сканировать путь к классам для всех допустимых реализаций Invokable и динамически загружать их во время выполнения.

Проблема здесь в том, что я могу получить доступ к name только через экземпляр, поэтому мне нужно создать копию каждого Invokable, чтобы сверить его имя с содержимым сообщения. Мое решение прямо сейчас состоит в том, чтобы хранить список предварительно созданных копий каждой реализации в отдельном классе, а затем вызывать метод, который извлекает и заменяет экземпляр из списка по имени.

Вместо этого я хотел бы иметь статический доступ к name, но я не могу придумать способ сделать это принудительно. Проще всего было бы иметь static abstract getName() в Invokable, но, к сожалению, Java не поддерживает его. Любые идеи?

Моя абстракция этой проблемы, вероятно, не самая лучшая, поэтому вот мой фактический исходный код. Соответствующие классы находятся в пакете command.


person cbryant02    schedule 03.07.2019    source источник
comment
Этот вопрос предлагает решение проблема, связанная с сохранением статического экземпляра класса-контейнера для информации о реализации, но она по-прежнему не применима, и я не могу преобразовать подклассы без потери доступа к информации.   -  person cbryant02    schedule 04.07.2019
comment
Я не уверен, что вы подразумеваете под принудительным исполнением. Как насчет статической карты «String, Class», которая заполняется при запуске? Через объект класса вы можете получить доступ к конструкторам, полям и т. д.   -  person President James K. Polk    schedule 04.07.2019
comment
Почему нельзя просто создать их все экземпляры и сохранить их список?   -  person chrylis -cautiouslyoptimistic-    schedule 04.07.2019
comment
@James K Polk Под принудительным исполнением я подразумеваю, что хочу по контракту требовать, чтобы подклассы Invokable заполняли поле name. Я не думаю, что карта будет намного лучше, чем мое текущее решение, особенно с учетом того, что мне все равно придется создавать экземпляры каждого класса хотя бы один раз, чтобы получить соответствующий ключ (т.е. name)   -  person cbryant02    schedule 04.07.2019
comment
@chrylis Это именно то, что я делаю, как ни странно. Отдельный класс, о котором я упоминал в третьем абзаце вопроса, заполняет List<Invokable> экземпляром каждой реализации Invokable, найденной в пути к классам. Метод предоставляется классом, который находит Invokable по имени, удаляет его экземпляр из списка, заменяет его новым экземпляром, а затем возвращает удаленный Invokable. Он отлично работает, но я бы предпочел выставлять name и любые другие поля статически, чтобы мне не приходилось постоянно хранить экземпляр каждой реализации в памяти.   -  person cbryant02    schedule 04.07.2019
comment
Вы используете пружину (или аналогичную инъекцию)? Если это так, вы можете сделать каждый экземпляр именованным компонентом и взять тот, который вам нужен, по имени, позволяя Spring обрабатывать все. Если нет, то надо :)   -  person Bohemian♦    schedule 04.07.2019
comment
@Bohemian На самом деле я использую Spring и понятия не имел, что он может это сделать. Со временем этот фреймворк нравится мне все больше и больше. Я попробую, когда вернусь на свою рабочую станцию.   -  person cbryant02    schedule 04.07.2019
comment
Я полагаю, что это все еще не обязательно контрактное решение, но в зависимости от того, как Spring заставляет его работать, мне это может понравиться больше.   -  person cbryant02    schedule 04.07.2019