Как реализовать обратные вызовы в Java

У меня есть класс CommunicationManager, который отвечает за связь с сервером.

Включает в себя методы login() а также onLoginResponse(), В случае входа пользователя метод login() должен быть вызван и когда сервер отвечает метод onLoginResponse() выполнен.

Я хочу связать действия с пользовательским интерфейсом. В классе GUI я создал экземпляр CommunicationManager с именем mCommunicationManager, Из класса GUI login() метод просто вызывается линией

mCommunicationManager.login();

То, что я не знаю, как сделать, это привязать метод из класса GUI к onLoginResponse(), Например, если класс GUI включает метод notifyUser() который отображает сообщение, полученное от сервера.

Я был бы очень признателен, если бы кто-нибудь мог показать, как связывать методы для выполнения метода из класса GUI (например, GUI.notifyUser()) когда экземпляр класса mCommunicationManager получает сообщение с сервера и метод CommunicationManager.onLoginResponse() выполнен.

Спасибо!

4 ответа

Решение

Здесь есть два паттерна, которые вы можете использовать. Одним из них является шаблон публикации / подписки или наблюдателя, упомянутый Питом. Я думаю, что это, вероятно, то, что вы хотите, но, поскольку в вопросе упоминается обязательный метод для последующего выполнения, я подумал, что должен упомянуть шаблон Command.

Шаблон Command - это обходной путь для того факта, что java не рассматривает методы (функции) как объекты первого класса, и поэтому их невозможно передать. Вместо этого вы создаете интерфейс, который можно передавать и который содержит необходимую информацию о том, как вызывать оригинальный метод.

Итак, для вашего примера:

 interface Command {
     public void execute();
 }

и затем вы передаете экземпляр этой команды при выполнении login() функция (непроверенная, я всегда забываю, как правильно получить анонимные классы):

 final GUI target = this;
 command = new Command() {
     @Override
     public void execute() {
         target.notifyUser();
     }
 };
 mCommunicationManager.login(command);

А в функции login() (менеджер сохраняет ссылку на команду):

public void login() {
    command.execute();
}

редактировать: я, вероятно, должен упомянуть, что, хотя это общее объяснение того, как это работает, в Java уже есть некоторая сантехника для этой цели, а именно ActionListener и связанные классы (actionPerformed() в основном execute() в Command). Тем не менее, они в основном предназначены для использования с классами AWT и / или Swing, и, следовательно, имеют функции, характерные для этого варианта использования.

Идиома, используемая в Java для достижения поведения обратного вызова, - Слушатели. Построить интерфейс с методами для событий, которые вы хотите, иметь механизм для регистрации объекта слушателя с источником событий. Когда происходит событие, вызовите соответствующий метод для каждого зарегистрированного слушателя. Это общий шаблон для событий AWT и Swing; для случайно выбранного примера см. FocusListener и соответствующий объект FocusEvent.

Обратите внимание, что все события в Java AWT и Swing в конечном итоге наследуются от EventObject, и соглашение заключается в вызове слушателя. SomethingListener и событие SomethingEvent, Хотя вы можете с легкостью называть свой код как угодно, легче поддерживать код, который соответствует соглашениям платформы.

Вы можете посмотреть на SWT-фрагменты (посмотрите на слушателей)

http://www.eclipse.org/swt/snippets/

или вы используете класс runnable, перезаписывая метод run вашим кодом обратного вызова при создании экземпляра

Насколько я знаю, Java не поддерживает привязку методов или делегатов, как в C#.

Возможно, вам придется реализовать это через интерфейсы (например, как слушатель команд.).

Может быть, этот сайт будет полезен:

http://www.javaworld.com/javaworld/javatips/jw-javatip10.html

Другие вопросы по тегам