Crie um evento customizado em Java


Respostas:


421

Você provavelmente deseja examinar o padrão de observador .

Aqui está um exemplo de código para você começar:

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..."
    }
}

Artigo relacionado: Java: Criando um Evento Customizado


Existe uma razão legítima para que stackoverflow.com/suggested-edits/237242 não tenha passado? Ele mostra como fazer isso com 2 classes, como a pergunta originalmente feita.
GlassGhost

2
E se vários threads estiverem gerando os eventos de origem, isso será sincronizado corretamente?
Mike G

Depende da siruação. Cada ouvinte será notificado de acordo com a ordem em que se registrou. (Btw, eu não entendo o que você quer dizer com vários segmentos aqui O código ouvinte será exectued no mesmo segmento que causou o evento para ocorrer..)
aioobe

8
@ GllGhost: Foi rejeitado porque era basicamente uma reescrita total. As edições na resposta de outra pessoa são boas se corrigirem erros de digitação, formatação e links quebrados, mas não devem alterar radicalmente o conteúdo. (Algumas exceções se aplicam para as mensagens marcadas como "wiki comunidade".)
Chao

1
O java não tem nada incorporado para isso? Eu realmente preferiria fazer isso em padrão abstrato, não implementar o loop for para todos os eventos.
Tomáš Zato - Restabelece Monica


21

Existem três maneiras diferentes de configurar isso:

  1. Thrower dentro de Catcher
  2. Catcher dentro de Thrower
  3. Throwere Catcherdentro de outra classe neste exemploTest

O EXEMPLO DO GITHUB DO TRABALHO QUE EU ESTOU CITANDO O padrão é a Opção 3, para tentar os outros "Optional"simplesmente descomente obloco de código da classe"" que você quer que seja a principal e defina essa classe como a${Main-Class}variável nobuild.xmlarquivo:

4 coisas necessárias para jogar código lateral:

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 Coisas necessárias em um arquivo de classe para receber eventos de uma classe

/*_______________________________________________________________*/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 . . .
}

6
@ GllGhost: O problema é que mainé estático, e não existe thisuma função estática. Você precisa criar um new Catcher1()lugar e passar essa instância. 1.5 também não permitia thisem um contexto estático; Tenho certeza de que nunca foi permitido.
cHao 23/01

6
@ GllGhost: O código que usa thisestá em um construtor, não em main. É por isso que funciona. Mova para main, e eu garanto que não. É o que as pessoas tentam lhe dizer e sua resposta está tentando fazer. Eu não dou a mínima para o que está no github - eu me importo com o que está no SO. E o que você tem no SO está quebrado.
cHao 3/08/14

7
@ GllGhost: Eu não acho que sua resposta seja inadequada no geral. O problema que vejo com isso é que o código não trabalho como é - você está tentando usar thisa partir main, que não irá compilar em qualquer versão lançada do Java. Se essa parte estava em um construtor ou se maincriou a new Catcher1()e usou isso em vez de this, deve funcionar, mesmo em 1.6+.
cHao 3/08/14

6
@GlassGhost: "Um método declarado staticé chamado de método de classe. Um método de classe é sempre invocado sem referência a um objeto específico. Uma tentativa de referenciar o objeto atual usando a palavra-chave thisou a palavra-chave superou os parâmetros de tipo de qualquer ambiente circundante. declaração no corpo de um método de classe resulta em um erro em tempo de compilação. " - JLS para Java 5, §8.4.3.2
cHao 03/08/14

31
Este é um dos estilos de código mais estranhos que eu já vi
Eric

4

O seguinte não é exatamente o mesmo, mas semelhante, eu estava procurando por um trecho para adicionar uma chamada ao método da interface, mas encontrei esta pergunta, então decidi adicionar esse trecho para aqueles que o pesquisavam como eu e encontrei esta pergunta :

 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);
        }    
    }

O uso é o seguinte:

myClassObj.setDataLoadFinishedListener(new MyClass.DataLoadFinishedListener() {
            @Override
            public void onDataLoadFinishedListener(int data_type) {
                }
            });
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.