Шаблон для создания экземпляров класса по целочисленному идентификатору? - PullRequest
0 голосов
/ 15 сентября 2009

Я читаю поток, который предоставляет идентификатор (простое int). В зависимости от int следуют разные данные, которые мне нужно превратить в объекты. До сих пор я создавал классы для каждого типа объекта, и каждый класс предоставляет метод read (InputStream input), который считывает любые данные, которые нужно прочитать для этого типа объекта (все классы объектов наследуются от общего базового класса).
Тем не менее, существуют многочисленные идентификаторы и, следовательно, многочисленные классы. Какой самый элегантный способ определить и создать экземпляр класса? Самый наивный подход, который я попробовал сначала, состоял в том, чтобы иметь блок переключателей для создания экземпляров, но я обнаружил, что он загромождает код (необоснованно). Это также вынуждает меня иметь каждый класс доступным во время компиляции.
Вторая попытка состояла в том, чтобы создать карту, которая отображает каждое int в класс и использует newInstance () для создания объектов. По-прежнему существует проблема, связанная с тем, что мне нужно инициализировать карту, которая требует наличия каждого класса, доступного во время компиляции. Он более или менее просто переместил беспорядок из одного места в другое.
Удаление зависимостей времени компиляции не требуется, это будет просто бонус, если это возможно. Основная цель - избежать стандартного кода.

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

Ответы [ 3 ]

5 голосов
/ 15 сентября 2009

Альтернативный подход заключается в том, чтобы по-прежнему использовать карту, но по существу использовать позднюю привязку, если это предпочтительно. Вы даже можете сохранить конфигурацию в файле свойств, например:

1=java.lang.String
2=my.class.Something
...etc...

Затем вы делаете что-то вроде этого:

Map<Integer,ObjectFactory> loader = ... // load from properties; fairly trivial

при условии:

public class ObjectFactory {
  private Final String className;
  private transient Class clazz;

  public ObjectFactory(String className) {
    this.className = className;
  }

  public Object createInstance() {
    try {
      if (clazz == null) {
        clazz = Class.forName(className);
      }
      return clazz.newInstance();
    } catch (Exception e) {
      throw new IllegalStateExxception("Could not crate " + className, e);
    }
  }
}
1 голос
/ 15 сентября 2009

У вас может быть реестр с прототипами.

Прототип каждого класса, который вы хотите создать (в определенный момент времени), может быть добавлен к вашему объекту реестра во время выполнения, каждый из этих прототипов будет иметь свой собственный уникальный целочисленный идентификатор.

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

Внутренне реестр может представлять собой (хэш) карту для быстрого поиска, но он также может быть просто списком прототипов (убедитесь, что все прототипы реализуют общий интерфейс, с которым может работать реестр). Лучше всего, не нужно размышлять!

1 голос
/ 15 сентября 2009

Я думаю, что ваше картографическое решение звучит нормально, но перенесите начальную настройку карты из кода Java в файл конфигурации. (Class.forName поможет здесь)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...