I want to do something like this in Java but I don't know the way:
When event "object 1 say 'hello'" happens, then object 2 responds to that event by saying "hello".
Can somebody give me a hint or sample code?
I want to do something like this in Java but I don't know the way:
When event "object 1 say 'hello'" happens, then object 2 responds to that event by saying "hello".
Can somebody give me a hint or sample code?
You probably want to look into the observer pattern.
Here's some sample code to get yourself started:
import java.util.*;
// An interface to be implemented by everyone interested in "Hello" events
interface HelloListener {
void someoneSaidHello();
}
// Someone who says "Hello"
class Initiater {
private List<HelloListener> listeners = new ArrayList<HelloListener>();
public void addListener(HelloListener toAdd) {
listeners.add(toAdd);
}
public void sayHello() {
System.out.println("Hello!!");
// Notify everybody that may be interested.
for (HelloListener hl : listeners)
hl.someoneSaidHello();
}
}
// Someone interested in "Hello" events
class Responder implements HelloListener {
@Override
public void someoneSaidHello() {
System.out.println("Hello there...");
}
}
class Test {
public static void main(String[] args) {
Initiater initiater = new Initiater();
Responder responder = new Responder();
initiater.addListener(responder);
initiater.sayHello(); // Prints "Hello!!!" and "Hello there..."
}
}
Related article: Java: Creating a custom event
What you want is an implementation of the observer pattern. You can do it yourself completely, or use java classes like java.util.Observer
and java.util.Observable
There are 3 different ways you may wish to set this up:
Thrower
inside of Catcher
Catcher
inside of Thrower
Thrower
and Catcher
inside of another class in this example Test
THE WORKING GITHUB EXAMPLE I AM CITING Defaults to Option 3, to try the others simply uncomment the "Optional
" code block of the class you want to be main, and set that class as the ${Main-Class}
variable in the build.xml
file:
4 Things needed on throwing side code:
import java.util.*;//import of java.util.event
//Declaration of the event's interface type, OR import of the interface,
//OR declared somewhere else in the package
interface ThrowListener {
public void Catch();
}
/*_____________________________________________________________*/class Thrower {
//list of catchers & corresponding function to add/remove them in the list
List<ThrowListener> listeners = new ArrayList<ThrowListener>();
public void addThrowListener(ThrowListener toAdd){ listeners.add(toAdd); }
//Set of functions that Throw Events.
public void Throw(){ for (ThrowListener hl : listeners) hl.Catch();
System.out.println("Something thrown");
}
////Optional: 2 things to send events to a class that is a member of the current class
. . . go to github link to see this code . . .
}
2 Things needed in a class file to receive events from a class
/*_______________________________________________________________*/class Catcher
implements ThrowListener {//implement added to class
//Set of @Override functions that Catch Events
@Override public void Catch() {
System.out.println("I caught something!!");
}
////Optional: 2 things to receive events from a class that is a member of the current class
. . . go to github link to see this code . . .
}
The following is not exactly the same but similar, I was searching for a snippet to add a call to the interface method, but found this question, so I decided to add this snippet for those who were searching for it like me and found this question:
public class MyClass
{
//... class code goes here
public interface DataLoadFinishedListener {
public void onDataLoadFinishedListener(int data_type);
}
private DataLoadFinishedListener m_lDataLoadFinished;
public void setDataLoadFinishedListener(DataLoadFinishedListener dlf){
this.m_lDataLoadFinished = dlf;
}
private void someOtherMethodOfMyClass()
{
m_lDataLoadFinished.onDataLoadFinishedListener(1);
}
}
Usage is as follows:
myClassObj.setDataLoadFinishedListener(new MyClass.DataLoadFinishedListener() {
@Override
public void onDataLoadFinishedListener(int data_type) {
}
});
Terminology
Usually, when people implement the observer pattern, they require the dispatcher to exist before any listener can subscribe to it. But there is a better way called Signals.
Signals is an events library. It decouples the dispatcher's listeners by introducing a Signal object that allows both register listeners and dispatch events. Signals are automatically created from an interface via Proxy. It takes care of all the boilerplate code for managing listeners, plus it adds some nice sugar code API.
interface Chat{
void onNewMessage(String s);
}
class Foo{
Signal<Chat> chatSignal = Signals.signal(Chat.class);
void bar(){
chatSignal.addListener( s-> Log.d("chat", s) ); // logs all the messaged to Logcat
}
}
class Foo2{
Signal<Chat> chatSignal = Signals.signal(Chat.class);
void bar2(){
chatSignal.dispatcher.onNewMessage("Hello from Foo2"); // dispatches "Hello from Foo2" message to all the listeners
}
}
In this example, the Signal is automatically created from the Chat
interface. It allows Foo
to register for it and Foo2
to dispatch new messages without interaction.
Disclaimer: I am the author of Signals.
Ahem, I recently needed to do events and I stumbled upon this topic. I decided to add my own implementation based on the C# version of events, maybe someone will read it and it will be useful to him :
@FunctionalInterface
public interface Action{
void accept(Object... args);
}
public class CustomEvent {
protected List<Action> listeners = new ArrayList<>();
public void addListener(Action arg0){
listeners.add(arg0);
}
public void removeListener(Action arg0){
listeners.remove(arg0);
}
public void invoke(Object... args){
for (Action listener : listeners) {
listener.accept(args);
}
}
}
public class Example1 {
public CustomEvent onValueChanged;
private void doSomething(){
onValueChanged.invoke(); // or .invoke(arg0, arg1, ...)
}
}
public class Example2 {
private Example1 example1;
private Action linkToAction;
private void init(){
example1 = new Example1();
linkToAction = args -> {
doSomethingAnother(); // or doSomethingAnother((Type)args[0], (Type)args[1], ...)
}
example1.onValueChanged.addListener(linkToAction);
}
public void doSomethingAnother(){}
public void unsubscribe(){
example1.onValueChanged.removeListener(linkToAction);
}
}
This is a simple example, the implementation of the Action interface, that I made, is based on the Consumer interface, so the method names are similar, but you can also change it.