1

I have the class AircraftManager that keeps track of a list of Aircraft objects and a list of AircraftListener objects.

A DataSource (custom class, not sql related) object retrieves information from an external source, the data sources decodes the message and calls appropriate logic on the aircraft, i.e setAltitude, setHeading. The program is designed to plot Aircraft onto a live map.

calling the setters on Aircraft should trigger the onAircraftUpdate(Aircraft aircraft, String fieldName, Object fieldValue) method on each registered AircraftListener in the AircraftManager

This first of all requires the Aircraft to keep a reference of the AircraftManager to invoke methods on the event listeners as such:

public void setAltitude(int altitude) {
    if (this.altitude != altitude) {
        this.altitude = altitude;
        this.aircraftManager.getListeners().forEach((aircraftListener ->
                aircraftListener.onAircraftValueChanged(this, "altitude", longitude)));
    }
}

This also means AircraftManager has a responsibility to keep hold of all AircraftListeners as well as Aircraft.

My question is whether this solution is satisfactory, any improvements/changes you would make. It's also worth noting that a class will not want to add a listener upon a single aircraft, but all aircraft.

  • 1
    Recommended Reading: blog.cleancoder.com/uncle-bob/2014/05/08/… -- also, another thing you could consider when it comes to passing events between objects might be to use a Mediator, such as the one in this LIbrary: github.com/sizovs/PipelinR – Ben Cottrell Mar 2 at 17:10
  • Who is deciding to change the altitude, and why? – Greg Burghardt Mar 2 at 17:21
  • What, at a high level, does the application do? – Greg Burghardt Mar 2 at 17:22
  • @GregBurghardt A DataSource (custom class, not sql related) object retrieves information from an external source, the data sources decodes the message and calls appropriate logic on the aircraft, i.e setAltitude, setHeading. The program is designed to plot Aircraft onto a live map. – cobra12 Mar 2 at 17:24
  • 1
    This is crucial information to add to you question text. Can you edit your question and add this info? It gets lost in comments too easily. – Greg Burghardt Mar 2 at 17:26
2

The example code you provided feels like a variant of something known as an EventBus where consumers can register for the type of event they care about. The single responsibility for the EventBus is to deliver events of a specific type to all the listeners registering for that event.

The listening code would register for the type (or base type) of event it wants to receive. In pseudo code it would look like this:

eventBus.register<AirplaneEvent>(event -> onAircraftChanged(event));

In your producer side of the equation you would publish the specific event:

public void setAltitude(int altitude) {
    if (this.altitude != altitude) {
        this.altitude = altitude;
        this.eventBus.publish(new AltitudeChangedEvent(this, altitude));
    }
}

Another solution would simply be a publish/subscribe message bus.

In each of these concepts the idea of publish and subscribe are integral parts of the responsibility of delivering events to the listeners. Now, what you don't see in this example is the forEach() call you did in the listener. That's the responsibility of the EventBus or Message Bus. Inside the EventBus would be the filtering logic to deliver only the events/messages that a listener had registered for. None of the listeners are exposed to the class calling publish()

If you needed to handle dead-letter queuing or managing unhandled events in some way, that is solely the responsibility of the EventBus or message queue. None of the code from the subscriber or publisher role must change.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.