Java загружает пользовательские классы во время выполнения - PullRequest
3 голосов
/ 24 мая 2010

Я работаю над симуляцией робота на Java (приложение Swing). У меня есть абстрактный класс «Робот», из которого получены различные типы роботов, например,

public class StupidRobot extends Robot {
   int m_stupidness;
   int m_insanityLevel;
   ...
}

public class AngryRobot extends Robot {
   float m_aggression;
   ...
}

Как видите, каждый подкласс робота имеет свой набор параметров.

То, что я хотел бы сделать, это управлять настройкой симуляции в начальном пользовательском интерфейсе. Выберите количество и тип роботов, дайте ему имя, заполните параметры и т. Д.

Это один из тех случаев, когда, будучи программистом-динозавром и новичком в Java, мне интересно, есть ли какие-то вещи / идеи более высокого уровня, которые могут мне здесь помочь. Итак, вот что у меня есть:

(1) Интерфейс пользователя

Список прокрутки типов роботов слева. Кнопки «Добавить >>» и «<< Удалить» посередине. Прокручиваемый по умолчанию список роботов справа. Кнопка «Установить параметры» внизу. (Поэтому, если вы хотите AngryRobot, вы должны выбрать AngryRobot в левом списке, нажать «Добавить >>», и справа появится «AngryRobot1».)

Выбирая робота справа, нажмите кнопку «Установить параметры ...», которая вызовет еще одно диалоговое окно модели, в котором вы заполните параметры. Различные диалоги для каждого Тип робота.

(2) Структуры данных реализации

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

enum ROBOT_TYPE {STUPID, ANGRY, etc}

public class RobotInitializer {
    public ROBOT_TYPE m_type;
    public string m_name;
    public int[] m_int_params;
    public float[] m_float_params;
    etc.

Конструктор инициализатора создаст соответствующие массивы параметров длины на основе типа:

public RobotInitializer(ROBOT_TYPE type, int[] int_array, float[] float_array, etc){
     switch (type){
        case STUPID:
            m_int_params = new int[STUPID_INT_PARAM_LENGTH];
            System.arraycopy(int_array,0,m_int_params,0,STUPID_INT_PARAM_LENGTH);

        etc.

После создания всех экземпляров RobotInitializer они добавляются в HashMap.

Итерируя по HashMap, инициализатор моделирования берет элементы из Hashmap и создает соответствующие роботы.

Это разумно? Если нет, как это можно улучшить?

Спасибо

Ответы [ 3 ]

3 голосов
/ 24 мая 2010

Вы можете использовать отражение для динамической загрузки типов во время выполнения. См. Class.forName, чтобы узнать, как вы можете получить Class, если у него полное имя. Затем вы можете использовать метод isAssignableFrom, чтобы проверить, что класс является подклассом Robot. Вы можете определить некоторые методы шаблона в Robot, чтобы подклассы определяли конкретное поведение (например, какие свойства должны быть инициализированы). Получив определение класса, вы можете использовать метод newInstance() для создания экземпляров Robot (класс должен иметь конструктор по умолчанию, иначе вам следует использовать метод getConstructors() и использовать тот, который вам нужен). 1007 *

Я знаю, что есть другой способ загрузки определений классов с полным путем к файлу класса, но не могу вспомнить, как сейчас.

1 голос
/ 24 мая 2010

Как уже отмечалось, вы можете сделать Robot реализацией RobotInterface.Затем:

Class aRobotClass = Class.forName("robotClassName"); //or similar
Class[] aRobotClassImplements = aRobotClass.getIterfaces();
// Then ensure that "RobotInterface" exists in the aRobotClassImplements array.

RobotInterface должен определить методы получения и установки для свойств робота.

Я предполагаю, что у каждого робота могут быть различные свойства.Можно динамически исследовать экземпляр Robot и создавать соответствующие кнопки / контроллеры.Например:

Field[] robotFields = aRobotClass.getFields();

for (Field field : robotFields) {
   JButton jbutton = new JButton(field.getName());
   //assuming this class implements ActionListener
   jbutton.addActionListener(this);
   // Then assume we have a private class representing a button )
   this.hashMapOrVectorOfButtons.add(new PrivateButton(field));
   jpanel.add(jbutton);
   // etc etc
}

Позже в actionPerformed зациклите хэш-карту или вектор зарегистрированных кнопок.(Field.getName (). (Равно actionEvent.getActionCommand ())).Затем манипулируйте соответствующим полем в вашем экземпляре робота.

1 голос
/ 24 мая 2010

Вы также можете использовать RMIClassLoader, хотя я бы порекомендовал ответ Fede, если вы можете использовать его таким образом.

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