1

I'm designing an API that receives several event types all inheriting from a common base class. So lets say EventA and EventB inherit from BaseEvent These events need to go trough several different processors. So I though the visitor pattern would be a good choice here. So the BaseEvent would look something like this:

public class BaseEvent implements Visitable {
    void visit(Visitor visitor) {
        visitor.visit(this);
    }
}

So now I have an API that includes the Visitable and the Visitor types, but they are not really related to the API. the processing is only done on the receiving side.

So I though about defining the API types without the Visitor interfaces and to define new types that include the visitors on the receiver of the events But then I have to translate the API types to the new types and I don't see a way to do it without using instanseof for every event type

Does anyone see a solution for this? Or maybe some other design that can solve the problem?

Thanks

Edit (Adding Some more info): The events just hold information and on the receiver side they need to go through the processors. I currently have 3 types of events (but that is likely to grow), and 2 processors (this can also change but less likely) I wanted to use the visitor pattern cause it forces me to add new methods to the processors when new events are added If I just override the process() method for each type I will only catch errors in runtime when new events are added

Nir Brachel
  • 413
  • 3
  • 12
  • 1
    Your goal description isn't really clear. Can you give us a "flow chart" type of description of what you expect to be input and output? – Tschallacka May 13 '16 at 11:36
  • Do all events have to be handled by processors? Will you be adding new events often? Dynamically? Perhaps a publish-subscribe mechanism would be better? By the way, since your event is not a complex data structure to be traversed, I do not really see the advantage of the visitor pattern here. Why not just `processor.handle(event)` ... same as `visitor.visit(event)` ? – plalx May 13 '16 at 15:30

2 Answers2

1

I'm not sure what your use-case or architecture looks like, but I had a similar issue I think, with a trade routing system. There were events defined for routing a trade, getting acknowledgements, getting executions, etc. Events were only dumb objects, and there were processors with lots of if statements with instanceofs.

We decided to redesign the whole thing using "real" objects instead of events and processors. This means the "events" are no longer just holders of information, but they can "process themselves". Since they (at least in our use-case) had all the necessary information, they can actually process themselves better than one or multiple "external" processors.

There were multiple curious sideffects:

  • Dependencies became much clearer and easier.
  • We got rid of most of getters/setters, because asking an object for all of its information became unnecessary. This I found pretty cool.

So basically instead of a "bean" like this:

public class LimitOrderExecution ... {
    private int executedAmount;
    private int remainingAmount;
    private BigDecimal executionPrice;
    private Order order;
    ...more fields...

    ... setter / getter for everything ...
}

We now have:

public class LimitOrderExecution ... {
    ...fields...

    public void apply() {
        ...applies itself using other objects...
    }
}
Robert Bräutigam
  • 7,514
  • 1
  • 20
  • 38
  • This is very similar to my problem – Nir Brachel May 17 '16 at 14:26
  • This is very similar to my problem. Although I didn't like the notion of defining API events (which are actually messages) as objects with functionality. I intended to solve the problem of having to process the events with the visitor pattern instead of putting the processing functionality inside the events (this decouple the processing from the event), Buy I was still left with api events that has functionality inside – Nir Brachel May 17 '16 at 15:02
  • This is basically following the principle tell, don't ask. I have a similar problem but I cannot apply this principle in a straightforward manner: the component triggering events (an observable) is not aware of the logic that the observers must do, the observer and the observable are decoupled components, that's the whole reason I introduce this pattern in the first place. Do you have ideas for this situation? Let's rubber duck. – Flavius Jan 01 '21 at 20:19
0

There are several options:

instanceof

instanceof may not be that bad. Neither in regards of performance, nor from a coding-style POV. So why even use some workaround, if you don't need to?

Method overriding

Simply override the method for each Event that needs to be processed separately:

class EventReceiver{
    void eventReceived(BaseEvent e){
    }

    void eventReceived(EventA e){
    }

    ...
}

Same could of course be done for your visitor-pattern. Though the visitor-pattern would be rather superfluous here.

Another event-structure

If you don't want to distinguish your events by type, just add a variable that allows identification of the event without instanceof. Though that'd just be a workaround to the instanceof operator.

Community
  • 1
  • 1