Как выбрать определенный класс для создания экземпляров во время выполнения в Java?

Я получаю около 20 классов с именами A, B, C,...X, Y, Z.

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

Я могу написать оператор switch case, чтобы сделать это, например:

switch (msg):
  case "A" :
    class = new A();
    break;
  case "B" :
    class = new B();
    break;
  case "C" :
    class = new C();
    break;
...

Есть ли более краткий способ сделать это? Я не могу представить, насколько скучна кодировка, если я получу 1000 классов.

6 ответов

Решение

Ты можешь использовать Class.forName() за это:

Class c = Class.forName("foo.bar.MyClass"); // requires full class name including package
Object object = c.newInstance();

Смотрите документацию Class.forName() Больше подробностей. Эти особенности называются отражением. Oracle предоставляет хороший раздел документации для такого рода функций.

Другие предложили использовать фабрику, и они правы.

Я предпочитаю использовать enum для моей фабрики.

interface I {

}

class A implements I {

}
class B implements I {

}
class C implements I {

}
enum Factory{
  A {
    @Override
    A create() {
     return new A(); 
    } 
  },
  B {
    @Override
    B create() {
     return new B(); 
    } 
  },
  C {
    @Override
    C create() {
     return new C(); 
    } 
  };

  // Constructors.
  abstract I create();

  // Construct a named class.
  public I create(String type) {
    return Factory.valueOf(type).create();
  }
}

Попробуйте это: -

Class myclass = Class.forName("Your.Class.MyClass");
Object o= myclass .newInstance();

forName ()

Возвращает объект Class, связанный с классом или интерфейсом с заданным именем строки.

Прежде всего, такая проблема присуща хорошему дизайну. Тип метода, о котором вы говорите, - это метод Factroy.

Вы можете использовать case, но чаще используется блок if-else. Так...

if(msg.equals(A)) {
  return new A();
} else if(msg.equals(B)) {
  return new B();
} ....

Здесь, предполагая, что A & B являются строками, мне нравится определять их как константы (public static final).

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

  1. Получить Class экземпляр из ClassLoader, передавая имя, которое вам нужно.
  2. Вызов newInstance в теме.

Как я вижу, у каждого есть свое решение, поэтому я покажу вам мое

тебе нужно:

    interface MyInterface {
    }

    class A implements MyInterface {
    }

    class B implements MyInterface {
    }

    interface Factory {
    MyInterface createInstance();
}

    class FactoryA implements Factory {

    @Override
    public MyInterface createInstance() {
        return new A();
    }
}

class FactoryB implements Factory {

    @Override
    public MyInterface createInstance() {
        return new B();
    }
}

enum MyEnum {
    A(new FactoryA()), B(new FactoryB());
    Factory factory;

    MyEnum(Factory factory) {
        this.factory = factory;
    }

    MyInterface getInstance() {

        return factory.createInstance();

    }

}

тогда все, что вам нужно сделать, это создать таблицу поиска, и ваш оператор switch будет заменен на MyEnum.find(msg).getInstance()

с этим решением вам не нужно беспокоиться об обработке любых исключений

Другие вопросы по тегам