Как реализовать обратные вызовы в Java
У меня есть класс CommunicationManager, который отвечает за связь с сервером.
Он включает методы login()
и onLoginResponse()
. В случае входа пользователя в систему должен быть вызван метод login()
, и когда сервер отвечает, метод onLoginResponse()
выполняется.
Что я хочу сделать, это связать действия с пользовательским интерфейсом. В классе GUI я создал экземпляр CommunicationManager под названием mCommunicationManager
. Из класса GUI метод login()
просто вызывается линией
mCommunicationManager.login();
То, что я не знаю, как это сделать, - это привязать метод из класса GUI к onLoginResponse()
. Например, если класс GUI включает метод notifyUser()
, который отображает сообщение, полученное от сервера.
Я был бы очень признателен, если бы кто-нибудь мог показать, как связать методы для выполнения метода из класса GUI (например, GUI.notifyUser()
), когда экземпляр класса mCommunicationManager
получает сообщение от сервера и метод CommunicationManager.onLoginResponse()
.
Спасибо!
Ответы
Ответ 1
Здесь два шаблона, которые я вижу, вы используете. Одним из них является публикация/подписка или шаблон наблюдателя, упомянутый Пит. Я думаю, что это, вероятно, то, что вы хотите, но, видя, что в вопросе упоминается привязка метода к последующему исполнению, я подумал, что я должен упомянуть Command pattern.
Шаблон 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, и, следовательно, имеют функции, характерные для этого случая использования.
Ответ 2
Идиома, используемая в Java для достижения обратного вызова, - это Listeners. Постройте интерфейс с методами для событий, которые вы хотите, имеете механизм регистрации объекта слушателя с источником событий. Когда происходит событие, вызовите соответствующий метод для каждого зарегистрированного слушателя. Это общий шаблон для событий AWT и Swing; для случайно выбранного примера см. FocusListener и соответствующий FocusEvent.
Обратите внимание, что все события в Java AWT и Swing наследуют в конечном счете от EventObject, и соглашение заключается в вызове слушателя SomethingListener
и событие SomethingEvent
. Хотя вы можете уйти от названия своего кода, как вам нравится, проще поддерживать код, который придерживается конвенций платформы.
Ответ 3
Вы можете посмотреть swt-фрагменты (посмотрите на слушателей)
http://www.eclipse.org/swt/snippets/
или вы используете класс runnable, заменив метод run своим кодом обратного вызова при создании экземпляра
Ответ 4
Насколько я знаю, Java не поддерживает привязку метода или делегаты, подобные С#.
Возможно, вам придется реализовать это через интерфейсы (например, как прослушиватель команд.).
Возможно, этот сайт будет полезен:
http://www.javaworld.com/javaworld/javatips/jw-javatip10.html