Решение о том, какой подкласс создавать во время выполнения

#java #reflection #subclass

#java #отражение #подкласс

Вопрос:

У меня есть Forum класс с несколькими подклассами, и я сохраняю имя подкласса в виде строкового поля в базе данных вместе со всеми другими полями. Когда я извлекаю объект, я хочу, чтобы это был экземпляр того же класса, что и раньше. Я мог бы выполнить множество инструкций if-else, чтобы определить, какой конструктор подкласса вызывать, но это было бы нелегко расширить.

Я нашел это решение, но оно кажется каким-то грязным:

     public static Forum createForum(int forumId, String kind) {
         try {
           Class cls = Class.forName("forum." kind);
           Constructor ct = cls.getConstructor(Integer.TYPE, String.class);
           Object retobj = ct.newInstance(forumId, kind);
           return (Forum) retobj;
         }
         catch (Throwable e) {
            System.err.println(e);
         }
         return null;
    }
  

Есть ли какое-либо лучшее решение?

Спасибо.

Комментарии:

1. Вы также могли бы использовать int.class вместо Integer.TYPE здесь.

Ответ №1:

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

Одной из альтернатив является создание интерфейса «factory object» для ваших Forum классов, а затем заполнение карты заводскими экземплярами для создания каждого из подклассов.

 public interface ForumFactory {
    public Forum createForum(String arg);
}

public class FooForumFactory implements ForumFactory {
    public Forum createForum(String arg) { return new FooForum(arg); }
}

Map<String, ForumFactory> factories = new HashMap<String, ForumFactory>();
factories.put("foo", new FooForumFactory());
factories.put("bar", new BarForumFactory());

...

// Create an instance ...
Forum forum = factories.get(forumType).createForum(forumName);
  

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

В долгосрочной перспективе использование ORM (например, Hibernate), вероятно, даст более элегантное решение.

Комментарии:

1. Мне нравится сообщение «есть новый ответ» … Я только начал писать довольно похожий ответ. 1.

Ответ №2:

Я думаю, что то, что вы ищете, — это сериализация объектов

(Эта страница немного перегружена рекламой, но на ней есть хорошая информация. Поиск в Google «сериализация объектов Java» вернет много информации)

Руководство по Oracle находится здесь: http://java.sun.com/developer/technicalArticles/Programming/serialization /

Комментарии:

1. Я тоже думал об этом, но это не обязательно подходит для базы данных SQL, потому что это повлияло бы либо на нормализацию, либо на возможность запроса. (Либо вы дублируете данные, либо запросить их невозможно.)

2. Зависит … он мог просто стремиться к постоянству. Вы также могли бы реализовать сериализацию, которая сохраняет его в БД точно так же, как он делает сейчас (не эффективно, но удобно). После этого вы переходите ко всему, что связано с ORM, с Hibernate и т.д… но полезно знать о сериализации.

Ответ №3:

Да, есть альтернатива — объектно-реляционное отображение (ORM), которое делает это за вас — и многое другое помимо этого. Фреймворки ORM для Java включают Hibernate и DataNucleus.

Комментарии:

1. Спасибо, но я не хочу перекодировать все управление сохраняемостью, которое у меня уже есть. Однако я рассмотрю это для своего следующего проекта.