Динамическая инициализация объектов

1

Следующий код является упрощенной версией. Write и Read классы, которые реализуют IAction интерфейс.

IAction newAction;
if (userInput.equalsIgnoreCase("WRITE")){
    newAction = new Write();
}
else if (userInput.equalsIgnoreCase("READ")){
    newAction = new Read();
}
...

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

  • 0
    Пока я думаю об использовании рефлексии, я нашел здесь много хорошего решения и несколько новых идей.
Теги:
object

4 ответа

2
Лучший ответ

Я зависим от того, что вы подразумеваете под "автоматически". Компьютеры делают вещи автоматически, но не раньше, чем кто-то запрограммировал что-то сделать автоматически. Вы, вероятно, имеете в виду "менее громоздкий". Вот подход, который использует функции Java 8.

// Make a Map that tells what word should be coupled to what action
Map<String, Supplier<IAction>> actionMapping = new HashMap<>();
actionMapping.put("WRITE", Write::new);
actionMapping.put("READ", Read::new);

// When you get user input, simply lookup the supplier
// in the map and call get() on it
IAction action = actionMapping.get(userInput.toUpperCase()).get();

Если вы не используете Java 8, вы можете использовать несколько иной (но похожий) подход:

// Map that tells what word should be coupled to what action
Map<String, Class<? extends IAction>> actionMapping = new HashMap<>();
actionMapping.put("WRITE", Write.class);
actionMapping.put("READ", Read.class);

// Lookup the action class for the input and instantiate it
IAction action = actionMapping.get(userInput.toUpperCase()).newInstance();
1

Да, возможно. Сначала создайте объект. Затем проверьте, существует ли имя класса, чтобы убедиться, что userinput является допустимым классом, а затем создайте динамический класс. После этого назначьте его своему объекту.

Object newAction = null;

 try {
  Class<?> clazz =  Class.forName( "your.fqdn.class."+userInput );
  Constructor<?> ctor = clazz.getConstructor(String.class);
  newAction = ctor.newInstance(new Object[] { ctorArgument });
  newAction = new your.fqdn.class."+userInput;
 } catch( ClassNotFoundException e ) {
   // catch an error if the class for the object does not exists.
}

Вы можете позже проверить класс, используя

if (newAction instanceOf MyClass) { } 
else if (newAction instanceOf Anotherclass) {}

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

1

Вы можете создать перечисление.

public enum Action implements IAction{
    READ,WRITE;
}

И используйте его в одной строке.

IAction action = Action.valueOf(userInput.toUpperCase());
0

Вы можете использовать перечисление и реализовать интерфейс для каждой константы перечисления. Вот пример реализации Consumer<String>:

public enum Action implements java.util.function.Consumer<String> {
    READ {
        @Override
        public void accept(String t) {
            System.out.println("Read: "+t);
        }
    },
    WRITE {
        @Override
        public void accept(String t) {
            System.out.println("Write: "+t);
        }
    };
}

Вы можете использовать его следующим образом:

Consumer<String> c = Action.valueOf("READ");
c.accept("Greetings!");
c = Action.valueOf("WRITE");
c.accept("Hello World!");

Это напечатает

Read: Greetings!
Write: Hello World!

Вы можете использовать String.toUpperCase() чтобы получить правильную константу, независимо от верхнего и нижнего регистра.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню