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