Укажите, какую реализацию интерфейса Java использовать в аргументе командной строки.

Скажем, у меня есть интерфейс Java Blender.java с различными реализациями Cuisinart.java, Oster.java, Blendtec.java и т. д. Теперь я хочу написать такую ​​программу:

public class Blendifier {
    // ...
    public static void main(String... args) {
        Blender blender = new Cuisinart();
        blender.blend();
    }
}

Но теперь, если я хочу использовать Blendtec вместо Cuisinart, мне нужно открыть исходный код, изменить код и перекомпилировать.

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

Но как перейти от строки, содержащей имя класса, к созданию фактического экземпляра этого класса?


person thecommexokid    schedule 21.04.2014    source источник
comment
Отражение. Или вы можете использовать DI-фреймворк, такой как Spring или Guice.   -  person Boris the Spider    schedule 22.04.2014
comment
Рефлексия — это огромная тема, о которой я ничего не знаю — я был бы рад, если бы кто-нибудь приблизил меня к тому, как я буду использовать ее для решения этой конкретной проблемы...   -  person thecommexokid    schedule 22.04.2014
comment
У меня нет времени прямо сейчас, чтобы написать полный ответ, но я все время использую способ отражения. Мой «AuthorizationService» использует файл конфигурации .properties для сопоставления имен разрешений с реализующими классами; мой «HtmlRenderer» просматривает настроенный пакет, чтобы увидеть, есть ли класс <Something>Renderer для любого тега, найденного во входных данных, например. <pre> находится во входных данных, он ищет класс PreRenderer в пакете, указанном при создании экземпляра «HtmlRenderer». Нет модифицирующего кода для добавления нового case или if при добавлении блендера новой марки.   -  person Stephen P    schedule 22.04.2014


Ответы (2)


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

public static Blender createBlender(String type){
    switch(type){
    case "Cuisinart": return new Cuisinart();
    case "Oster": return new Oster();
    //etc
    }
}

Затем вы просто передаете в него свой аргумент командной строки, и у вас будет все, что вам нужно.

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

person jedyobidan    schedule 21.04.2014

У вас есть несколько способов сделать это:

например если-иначе конструкция

Blender blender = null;
if (args[0].equals("Cuisinart")) {
   blender = new Cuisinart();
} else if (...)

где args[0] — ваш первый аргумент командной строки.

person Marcinek    schedule 21.04.2014