0

I want to write a simple event handling solution in Java with custom events. I've only find GUI based examples, using ActionListeners so far. I've included a code, that I wrote in C#.

I want to create something like this in Java:

using System;
using System.Threading;

namespace EventHandlingPractice
{
    class Program
    {
        static void Main(string[] args)
        {
            MusicServer mServer = new MusicServer();
            Sub subber = new Sub();

            mServer.SongPlayed += subber.SubHandlerMethod;

            mServer.PlaySong();

            Console.ReadKey();
        }
    }

    // this class will notify any subscribers if the song was played
    public class MusicServer
    {
        public event EventHandler SongPlayed;

        public void PlaySong()
        {
            Console.WriteLine("The song is playing");
            Thread.Sleep(5000);
            OnSongPlayed();
        }

        protected virtual void OnSongPlayed()
        {
            if (SongPlayed != null)
                SongPlayed(this, EventArgs.Empty);
        }
    }

    // this class is class is the subscriber
    public class Sub
    {
        public void SubHandlerMethod(object sender, EventArgs e)
        {
            Console.WriteLine("Notification from: " + sender.ToString() + " the song was played");
        }
    }
}
ErKhadi
  • 1
  • 1

1 Answers1

1

In Java you generally create an class for the event itself, extending from EventObject. The events of interest are defined in an interface ending with the name Listener, extending the interface EventListener.

The class which is able to broadcast events has a add/remove listener methods, where the interested party can register themselves.

Your code will work without following these conventions though, but they are (were?) meant for tools to understand names of the classes and methods.

Here a sample pseudo implementation for your domain:

public class Song {

}

public class SongEvent extends EventObject {
    private final Song song;

    public SongEvent(Object source, Song song) {
        super(source);
        this.song = Objects.requireNonNull(song);
    }

    public Song getSong() {
        return song;
    }
}

public interface SongListener extends EventListener {
    default void songStarted(SongEvent event) { }
    default void songPaused(SongEvent event) { }
}

public class SongServer {
    private List<SongListener> listeners = new ArrayList<>();

    public void addSongListener(SongListener listener) {
        listeners.add(listener);
    }

    public void removeSongListener(SongListener listener) {
        listeners.remove(listener);
    }

    public void playSong(Song song) {
        // ....
        SongEvent event = new SongEvent(this, song);
        listeners.forEach(l -> l.songStarted(event));
    }
}

public class MyEventHandler implements SongListener {
   @Override
   public void songStarted(SongEvent e) {
     System.out.printf("Now listening to %s%n", e.getSong().getName());
   }
}

In previous versions of Java it was standard to include an Adapter (SongAdapter) which would implement the listener interface as no-op operations. The reason for that was that if you would add events classes that extended from the adapter didn't need to add code. With Java 8 you can include default methods, so the Event Adapter pattern is not needed anymore.

M. le Rutte
  • 3,525
  • 3
  • 18
  • 31