Ответ
Паттерн Observer (Наблюдатель) — это поведенческий паттерн проектирования, который определяет отношение «один ко многим» между объектами. При изменении состояния одного объекта (Subject) все зависимые от него объекты (Observers) автоматически уведомляются и обновляются.
Зачем он нужен? Для реализации механизма подписки, позволяющего одним объектам следить за изменениями в других объектах, не создавая при этом жёсткой связи между ними.
Ключевые компоненты:
Subject(Издатель): Хранит список наблюдателей, предоставляет методы для подписки/отписки и уведомляет их об изменениях.Observer(Наблюдатель): Интерфейс с методомupdate(), который вызывается при изменении состояния издателя.ConcreteSubject: Конкретный издатель, хранящий состояние, интересующее наблюдателей.ConcreteObserver: Конкретный наблюдатель, который реагирует на уведомления от издателя.
Пример на Java:
import java.util.ArrayList;
import java.util.List;
// 1. Интерфейс наблюдателя
interface Observer {
void update(String message);
}
// 2. Интерфейс субъекта (издателя)
interface Subject {
void attach(Observer observer);
void detach(Observer observer);
void notifyObservers();
}
// 3. Конкретный издатель (например, система новостей)
class NewsAgency implements Subject {
private List<Observer> observers = new ArrayList<>();
private String latestNews;
public void setNews(String news) {
this.latestNews = news;
notifyObservers(); // Автоматическое уведомление при изменении
}
@Override
public void attach(Observer observer) {
observers.add(observer);
}
@Override
public void detach(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(latestNews);
}
}
}
// 4. Конкретный наблюдатель (например, новостной канал)
class NewsChannel implements Observer {
private String name;
private String receivedNews;
public NewsChannel(String name) {
this.name = name;
}
@Override
public void update(String news) {
this.receivedNews = news;
display();
}
public void display() {
System.out.println(name + " получил новость: " + receivedNews);
}
}
// 5. Клиентский код
public class Main {
public static void main(String[] args) {
NewsAgency agency = new NewsAgency(); // ConcreteSubject
Observer channel1 = new NewsChannel("Канал 1"); // ConcreteObserver
Observer channel2 = new NewsChannel("Канал 2"); // ConcreteObserver
agency.attach(channel1);
agency.attach(channel2);
// При изменении состояния издателя все наблюдатели уведомляются
agency.setNews("Вышла новая версия Java!");
// Вывод:
// Канал 1 получил новость: Вышла новая версия Java!
// Канал 2 получил новость: Вышла новая версия Java!
agency.detach(channel2);
agency.setNews("Важное обновление безопасности!");
// Вывод: Канал 1 получил новость: Важное обновление безопасности!
}
}
Преимущества:
- Слабая связность: Издатель не знает деталей реализации наблюдателей.
- Динамические отношения: Наблюдатели могут подписываться и отписываться во время выполнения.
- Широкое применение: Лежит в основе реактивных и событийно-ориентированных архитектур.
Недостатки:
- Наблюдатели могут получать уведомления в случайном порядке.
- Неуправляемое уведомление всех наблюдателей может привести к проблемам с производительностью, если их очень много.
Ответ 18+ 🔞
А, паттерн Observer, ёпта! Это ж классика, блядь, как "Муму" Тургенева, только без утоплений, надеюсь. Сейчас разжуём, что за зверь.
Представь, есть у тебя один важный чувак — Издатель (Subject). Он, сука, центр вселенной в своей маленькой схеме. А вокруг него крутится овердохуища Наблюдателей (Observers), которые ловят каждую его новую мысль. Он чихнул — они уже "будь здоров!" кричат. Он изменил своё внутреннее состояние — они все, как по команде, должны обновиться.
Зачем эта петрушка? Чтобы не бегать за каждым наблюдателем вручную, не орать "Эй, ты, пизда с ушами, я тут состояние поменял!". Издатель просто живёт своей жизнью, а все, кто на него подписался, получают оповещение на халяву. Слабая связность, блядь, мечта! Как в хорошем паблике: подписался — получай уведомления, надоело — отписался и иди нахуй.
Из чего этот конструктор лего состоит:
Subject(Издатель). Это царь и бог. У него есть список всех подписчиков-лоботрясов. Он умеет их добавлять (attach), выгонять пинком под жопу (detach) и орать на всех сразу "Чё встали, обновились, блядь!" (notifyObservers).Observer(Наблюдатель). Это интерфейс, контракт для всех, кто хочет слушать царя. Всего один метод —update(). Типа, "я готов, шли уже данные, ебать!"ConcreteSubject(Конкретный царь). Ну, например, Новостное агентство. У него есть главное — состояние (latestNews). Как только новость обновили, оно сразу орёт всем подписчикам.ConcreteObserver(Конкретный лоботряс). Допустим, Телеканал. Получил уведомление — обновил свою ленту и побежал показывать.
Смотри, как это в коде выглядит, сука (код не трогаем, он святой):
// 1. Интерфейс лоботряса (все должны уметь одно)
interface Observer {
void update(String message); // "Эй, чмошник, вот тебе новость!"
}
// 2. Интерфейс царя (все цари должны уметь командовать)
interface Subject {
void attach(Observer observer); // "Встань в строй!"
void detach(Observer observer); // "Свободен, пошёл нахуй!"
void notifyObservers(); // "Внимание, всем обновиться, блядь!"
}
// 3. Конкретный царь - Новостное агентство
class NewsAgency implements Subject {
private List<Observer> observers = new ArrayList<>(); // Список подписчиков
private String latestNews; // Его священное состояние
// Вот тут магия! Выпустили новость — и сразу всем сигнал!
public void setNews(String news) {
this.latestNews = news;
notifyObservers(); // Автоматический пинок всем наблюдателям
}
@Override
public void attach(Observer observer) {
observers.add(observer); // Подписался, молодец
}
@Override
public void detach(Observer observer) {
observers.remove(observer); // Отписался, иди в пизду
}
@Override
public void notifyObservers() {
// Проходим по всем и каждого пинаем
for (Observer observer : observers) {
observer.update(latestNews);
}
}
}
// 4. Конкретный лоботряс - Новостной канал
class NewsChannel implements Observer {
private String name;
private String receivedNews;
public NewsChannel(String name) {
this.name = name;
}
// Вот его реакция на пинок от издателя
@Override
public void update(String news) {
this.receivedNews = news; // Получил новость
display(); // И сразу её вывел
}
public void display() {
System.out.println(name + " получил новость: " + receivedNews);
}
}
// 5. Клиентский код, где всё оживает
public class Main {
public static void main(String[] args) {
NewsAgency agency = new NewsAgency(); // Создали царя
Observer channel1 = new NewsChannel("Первый блядский"); // Создали лоботрясов
Observer channel2 = new NewsChannel("Второй сопливый");
agency.attach(channel1); // Подписали первого
agency.attach(channel2); // Подписали второго
// Царь меняет состояние — все лоботрясы дёргаются!
agency.setNews("Вышла Java 25! Теперь код пишется силой мысли!");
// Вывод:
// Первый блядский получил новость: Вышла Java 25!...
// Второй сопливый получил новость: Вышла Java 25!...
agency.detach(channel2); // Второй канал отписался, пошёл нахуй
agency.setNews("Обнаружена уязвимость: все паттерны — хуйня!");
// Вывод: Только Первый блядский получил новость...
}
}
Плюсы, блядь:
- Связь слабая, как у алкоголика с реальностью. Издателю похуй, кто и как обрабатывает его новости.
- Подписки динамические. Хочешь — вставай в строй, не хочешь — вали. Во время работы программы!
- Применение — везде. Всякие GUI, event-driven архитектуры, реактивщина — тут этот паттерн пальцем делает.
Минусы, ёпта:
- Порядок уведомлений — хуй пойми. Кто первый встал, того и тапки. Может, это важно.
- Если наблюдателей дохуя, а издатель орет на всех без разбора — можно получить лавину обновлений и производительность ебать. Надо с умом.