Какой шаблон проектирования Java, чтобы избежать приведения объекта данных - PullRequest
0 голосов
/ 29 ноября 2018

В настоящее время я реализую асинхронную очередь событий внутри моего приложения - она ​​разработана для работы следующим образом: один компонент реагирует на ввод данных пользователем и помещает событие в очередь, а другой «слушатель» проверяет, есть ли событиеопределенного типа внутри очереди и запускает свою собственную бизнес-логику

. Могут быть различные типы событий (например, USER_MOUSE_CLICK, USER_KEYBOARD_CLICK и т. д.), и каждая реализация имеет свой собственный тип «объект-событие»

Этовыглядит так (я опускаю конструкторы - устанавливаю все поля и методы получения / установки - они просто обычные значения по умолчанию):

public abstract MyEvent<T> {
    private EventType eventType;
    private T eventData;
}

public MouseClickEvent extends MyEvent<ClickPoint> { // ClickPoint class contains x,y of mouse click
    public MouseClick(ClickPoint point) {
        super(EventType.USER_MOUSE_CLICK, point);
    }
}

public KeyboardClickEvent extends MyEvent<String> { // character that has been clicked on keyboard
    public MouseClick(String key) {
        super(EventType.USER_KEYBOARD_CLICK, key);
    }
}

У меня также есть служба с очередью MyEvent экземпляров и методомчтобы получить первое событие из предоставленного EventType, если оно существует - это похоже на

...
private List<MyEvent> queue;
...
public MyEvent fetchMyEvent(EventType eventType) {
    for(MyEvent event : queue) {
        if(event.getEventType().equals(eventType) {
            return event;
        }
    }
    return null;
}
...

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

// some listener logic
MouseClickEvent event = (MouseClickEvent ) eventService.fetchMyEvent(EventType.USER_MOUSE_CLICK);
log("The X point of mouse click was: " + event.getEventData().x);

Мне не нравится этот кастинг - я чувствую, что у меня нет контроля над типами, когда я получаю дажеи я вижу эту ситуацию как «слабое место» и генератор ошибок.Есть какой-то шаблон проектирования, чтобы избежать этого, или я должен перепроектировать всю систему?Или, может быть, это единственный путь, и мне все равно

1 Ответ

0 голосов
/ 29 ноября 2018

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

Чтобы использовать шаблон посетителя, вы должны: сначала: определить интерфейс посетителя:

public interface IEventVisitor {

    void visit(MouseClickEvent event);

    void visit(KeyboardClickEvent event);

}

Второй в вашем классе ужина определить метод absract acceptas:

public abstract MyEvent<T> {
    private EventType eventType;
    private T eventData;

    public abstract void accept(IEventVisitor visitor);
}

В-третьих: реализовать метод для каждого подкласса как:

public MouseClickEvent extends MyEvent<ClickPoint> { // ClickPoint class contains x,y of mouse click
    public MouseClick(ClickPoint point) {
        super(EventType.USER_MOUSE_CLICK, point);
    }

    public void accept(IEventVisitor visitor) {
        visitor.visit(this);

    }
}

И, наконец, реализовать интерфейс посетителя.

Использование будет выглядеть следующим образом, создайте экземпляр посетителя и вызовите event.accept (посетитель).

Event event = eventService.fetchMyEvent(EventType.USER_MOUSE_CLICK);
IEventVisitor visitor = new IEventVisitor() {

            @Override
            public void visit(MouseClickEvent event) {
                // logic goes here
            }

            @Override
            public void visit(KeyboardClickEvent event) {
                // logic goes here
            }
        };


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