Как реализовать обратные вызовы в 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