Обработка коллекций со смешанным POJOS, с различным обработчиком для каждого POJO - PullRequest
2 голосов
/ 21 апреля 2009

Я пытаюсь найти элегантное решение ООП для следующей проблемы.

Предположим, у нас есть коллекция POJOS, в данном случае событий, где каждый POJO, возможно, представляет собой отдельный класс. Нам нужно обработать эту коллекцию, используя разные правила для каждого класса POJO (или типа).

Основным предположением является то, что мы не можем украшать POJO соответствующими обработчиками, так как мы не контролируем их генерацию и не получаем коллекцию как есть. Таким образом, любой механизм для этого попадает в одну ловушку. Тем не менее, пункт 3 все еще рассматривает эту возможность.

Есть несколько возможных решений, некоторые очень уродливые, некоторые более изящные, но сложные:

  1. Очевидное и самое уродливое решение - использовать операторы instanceOf для передачи POJO в обработчик.
  2. Немного лучшая модификация 1 - использовать цепочку ответственности за это с цепным диспетчером, так что новым типам просто нужен новый диспетчер. Однако каждому диспетчеру по-прежнему требуется instanceOf.
  3. Создание расширенных объектов, а не POJOS, где каждый объект содержит ссылку на свой обработчик. Это создает связь между POJO и нашим процессором.
  4. Создать (я знаю, как сделать это правильно в Java) диспетчерскую службу, которая регистрирует обработчики для определенного класса событий, и использовать обобщенные типы (контейнер Typesafe, как в действующем Java) для отправки события обработчику.

4 - самый элегантный, но мне было интересно, есть ли лучшие идеи.

Ответы [ 5 ]

4 голосов
/ 21 апреля 2009

Упрощение № 4:

Используйте карту для хранения обработчика для каждого класса событий.

Map<Class, Handler> classHandlers = new HashMap<Class, Handler>();
classHandlers.put(EventA.class, new EventAHandler());
classHandlers.put(EventB.class, new EventBHandler());

Теперь используйте класс события, чтобы получить обработчик события.

Handler handler = classHandlers.get(event.getClass());
handler.handle(event);

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

1 голос
/ 21 апреля 2009

Предположим, у нас есть коллекция POJOS, в данном случае событий, где каждый POJO, возможно, является различным классом. Нам нужно обработать эту коллекцию, используя разные правила для каждого класса (или типа) POJO.

Поздравляем! Если классы POJO стабильны (новые типы классов добавляются не часто), вы только что описали мотивацию для использования шаблона посетителя!

Еще лучше, потому что вы вероятно хотите делать разные вещи с вашей коллекцией POJO, вы можете создать AbstractBaseVisitor и расширить его для обработки разных вещей, которые вам нужно сделать!

Для этого потребуется добавить крошечную оболочку вокруг каждого POJO, с одним классом оболочки для каждого класса POJO, чтобы добавить функцию visit(), которая вызывает Visitor.

0 голосов
/ 21 апреля 2009

Вопрос на самом деле вообще не зависит от языка. На некоторых языках вы можете легко украсить классы. Но давайте придерживаться Java. Даже там я говорю "это зависит".

Очевидная вещь, которую мы хотели бы сделать, это своего рода автоматическое обнаружение обработчиков. Например, аннотируйте свои обработчики аннотацией @Handler (handles = PojoA.class), затем сканируйте все классы, аннотированные @Handler (либо грязный способ, который в основном требует загрузки файлов классов, либо использование чего-то вроде Scannotation).

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

public interface Handler<T> {
    void handle(T object);
}

и найдите их в коде вашего диспетчера:

Collection<Handler> handlers = applicationContext.getBeansofType(Handler.class).values();
for (Handler handler : handlers) {
    Method handleMethod = handler.getClass().getMethod("handle", Object.class);
    Class<?> type = handleMethod.getParameterTypes()[0];
    register(type, handler);
}

(правда, приведенный выше код не проверен)

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

0 голосов
/ 21 апреля 2009

4 - лучшее из представленных вами решений. # 1 и 2 будет больно, когда вокруг них плавают экземпляры instanceof.

Другое решение: аннотируйте каждый класс с помощью метода диспетчера. Вам не понадобится центральное место для обработки вызовов диспетчера, и POJO / диспетчер не будут связаны вне аннотации.

0 голосов
/ 21 апреля 2009

Я использовал решение под номером 4 в этом сценарии, и я думаю, что оно хорошее. Я также буду искать другое мнение о лучшем решении.

...