mardi 2 juillet 2019

Design pattern class enhancement

I have the case where I have introduced a hierarchy of classes, as such:

Introducing a chain like pattern.

public abstract class EventHandler {

    private EventHandler next;

    public EventHandler chainWith(EventHandler next) {
        this.next = next;
        return next;
    }

    public void onEvent(Event event) {
        if (shouldHandle(event)) {
            onEventInternal(event);
        }
        onEventNext(event);
    }

    protected void onEventNext(Event event) {
        if (next != null) {
            next.handle(event);
        }
    }

    protected abstract void onEventInternal(Event event);

    protected abstract boolean shouldHandle(Event event);
}

Then I have several classes which extend that abstract class, and add their own implementation to onEventInternal and shouldHandle.

Example usage is:

EventHandler eventHandler = new EventHandlerImpl1();
eventHandler.chainWith(new EventHandlerImpl2()).chainWith(new EventHandlerImpl3());
eventHandler.onEvent(...something...);

The problem is that the implementations could have additional restrictions on when they should handle the event and when not to (additions to shouldHandle). But I cannot put these restrictions inside the implementations (inside shouldHandle method) because that would make the implementation NON reusable for cases where these restrictions are not there.

To explain it better, for example:

Lets imagine there is some Event.OPEN... EventHandlerImpl1 would have to handle events which are only Event.OPEN. So far, so good.

Now... this same handler will be used in a place where the same should apply (Event.OPEN only), but it should also be in specific interval of the day. That makes it unavailable to put it inside EventHandlerImpl1 because it would break the previous usage where the interval is not required.

I thought I could introduce a wrapper EventHandler implementation which adds that specific restriction (composition used).. in a decorator-like pattern style.

This however does not sound like a good solution to me, as the usage would get terrible:

EventHandler eventHandler = new EventHandlerImpl1();
eventHandler.chainWith(new EventHandlerTimeInterval(new EventHandlerImpl2())).chainWith(new EventHandlerTimeInterval(new EventHandlerImpl3());
eventHandler.onEvent(...something...);

I also thought about making it dynamic and being able to make a 'Builder' and adding Predicates to the EventHandler dynamically which would enable me to handle the event only if all predicates are ok.

Is there some pattern which I could use here to make my life easier. What design will be good in this case? What am I missing?

Aucun commentaire:

Enregistrer un commentaire