Паттерн Наблюдатель (Observer) в Java

Паттерн Наблюдатель (Observer) относится к поведенческим (behavioral) паттернам проектирования.

Основная цель данного паттерна это определение зависимости один-ко-многим между объектами, чтобы при изменении состояния объекта, все зависимые от него объекты получали уведомление и обновлялись автоматически.

Используйте паттерн Наблюдатель (Observer) в любой из следующих ситуаций:

  • когда абстракция имеет два аспекта, один зависит от другого. Инкапсуляция этих аспектов в отдельных объектах позволяет варьировать и повторно использовать их независимо.
  • когда изменение одного объекта требует изменения других, и вы не знаете, сколько объектов нужно изменить
  • когда объект должен иметь возможность уведомлять другие объекты, не делая предположений о том, кто эти объекты. Другими словами, вы не хотите, чтобы эти объекты были тесно связаны.

Типичный вариант использования: изменение в одном объекте приводит к изменению в других объектах.

Пример использования паттерна Наблюдатель на Java

Предположим у нас есть чат, все его пользователи должны получать обновления состояния чата. В следующем классе Chat наблюдатели (то есть пользователи чата) хранятся в списке observers. А сообщения чата в списке messages. При получении нового сообщения вызывается функция notifyObservers, отправляющая оповещение всем наблюдателям.

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

public class Chat {
    private static final Logger LOGGER = Logger.getLogger(Chat.class.getName());

    private List messages;
    private List observers;

    public Chat() {
        observers = new ArrayList<>();
        messages = new ArrayList<>();
    }

    public void addObserver(ChatObserver observer) {
        observers.add(observer);
    }

    public void removeObserver(ChatObserver observer) {
        observers.remove(observer);
    }

    public void addMessage(String message) {
        messages.add(message);
        LOGGER.info(String.format("Chat get new message: %s", message));
        notifyObservers(message);
    }

    private void notifyObservers(String message) {
        for (ChatObserver observer : observers) {
            observer.update(message);
        }
    }
}

Интерфейс наблюдателя прост - он имеет только 1 метод update для обновления наблюдателя.

public interface ChatObserver {
    void update(String message);
}

Вот примеры классов реализующих интерфейс ChatObserver и используемых в приложении в качестве пользователей чата.

import java.util.logging.Logger;

public class User implements ChatObserver {
    private static final Logger LOGGER = Logger.getLogger(User.class.getName());

    @Override
    public void update(String message) {
        LOGGER.info(String.format("%s get new message: %s", this.getClass().getName(), message));
    }
}

import java.util.logging.Logger;

public class Admin implements ChatObserver {
    private static final Logger LOGGER = Logger.getLogger(Admin.class.getName());

    @Override
    public void update(String message) {
        LOGGER.info(String.format("%s get new message: %s", this.getClass().getName(), message));
    }
}

Вот пример приложения чата с пользователями, использующего паттерн Наблюдатель.

public class App {
    public static void main(String[] args) {
        User user = new User();
        Admin admin = new Admin();

        Chat chat = new Chat();
        chat.addObserver(admin);
        chat.addObserver(user);

        chat.addMessage("Hi");
        chat.addMessage("Hello");
        chat.addMessage("Buy");

        chat.removeObserver(user);
        chat.addMessage("Buy-buy");
    }
}


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки