Створіть власну подію на Java


193

Я хочу зробити щось подібне на Java, але не знаю способу:

Коли подія "об'єкт 1 скаже" привіт ", тоді об'єкт 2 відповідає на цю подію, кажучи" привіт ".

Чи може хтось надати мені підказку чи зразок коду?



Відповіді:


421

Ви, мабуть, хочете заглянути в модель спостерігача .

Ось приклад коду, щоб розпочати роботу:

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

Пов'язана стаття: Java: Створення користувацької події


Чи є законна причина stackoverflow.com/sugges-edits/237242 не пройшов? Він показує, як це зробити з двома класами, як це було задано спочатку.
GlassGhost

2
Що робити, якщо кілька потоків генерують вихідні події, чи буде це правильно синхронізовано?
Майк Г

Залежить від сируації. Кожен слухач буде повідомлений відповідно до порядку, який вони зареєстрували. (До речі, я не розумію, що ви маєте на увазі під декількома потоками тут. Код слухача буде виконаний на тій самій нитці, що спричинила подію.)
aioobe

8
@GlassGhost: Відхилено, тому що в основному це було перезаписане. Редагування чужої відповіді добре, якщо вони виправляють помилки друку та форматування та порушені посилання тощо, але вони не повинні кардинально змінювати вміст. (Деякі винятки стосуються публікацій із позначкою "Вікі спільноти".)
cHao

1
Невже у Java немає для цього вбудованого? Я дійсно вважав за краще робити це за абстрактним малюнком, а не здійснювати цикл для кожної події.
Томаш Зато - Відновіть Моніку


21

Можна налаштувати це три різні способи:

  1. Thrower всередині Catcher
  2. Catcher всередині Thrower
  3. Throwerі Catcherвсередині іншого класу в цьому прикладіTest

ПРИКЛАД РОБОЧОГО ГІТУБУ Я ЦИТУЮ За замовчуванням Варіант 3, щоб спробувати інші просто відменшити "Optional" код код класу, який Ви хочете бути головним, і встановити цей клас як${Main-Class}змінну уbuild.xmlфайлі:

4 Необхідні речі для викидання бічного коду:

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 Речі, необхідні у файлі класу, щоб отримувати події від класу

/*_______________________________________________________________*/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
@GlassGhost: Проблема в тому, що вона mainє статичною, і немає такого поняття, як thisу статичній функції. Вам потрібно new Catcher1()десь створити і замість цього передати цей екземпляр. 1.5 також не дозволяв thisу статичному контексті; Я впевнений, що це ніколи не було дозволено.
cHao

6
@GlassGhost: Код, який використовується, thisзнаходиться в конструкторі, а не в main. Ось чому це працює. Перемістіть його main, і я гарантую, що цього не стане. Це те, що люди намагаються сказати вам, і те, що намагається зробити ваша відповідь. Я не біда, що на Github - мені байдуже, що на SO. І те, що у вас на SO, порушено.
cHao

7
@GlassGhost: Я не думаю, що ваша відповідь загалом недостатня. Проблема, яку я бачу з цим, полягає в тому, що код не працюватиме так, як є - ви намагаєтесь використовувати thisз main, який не буде компілюватися в жодній випущеній версії Java. Якщо б ця частина була замість конструктора, або якщо mainстворена new Catcher1()та використана, то замість цього thisвона повинна працювати навіть у 1.6+.
cHao

6
@GlassGhost: "Метод, який оголошується static, називається методом класу. Метод класу завжди викликається без посилання на конкретний об'єкт. Спроба посилання на поточний об'єкт за допомогою ключового слова thisабо ключового слова superабо посилання на параметри типу будь-якого оточення декларація в тілі методу класу призводить до помилки у компіляції. " - JLS для Java 5, §8.4.3.2
cHao

31
Це один з найдивніших стилів коду, який я коли-небудь бачив
Ерік

4

Далі не зовсім те саме, але схоже, я шукав фрагмент, щоб додати виклик методу інтерфейсу, але знайшов це питання, тому вирішив додати цей фрагмент для тих, хто його шукав, як я, і знайшов це питання :

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

Використання полягає в наступному:

myClassObj.setDataLoadFinishedListener(new MyClass.DataLoadFinishedListener() {
            @Override
            public void onDataLoadFinishedListener(int data_type) {
                }
            });
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.