1. Что такое паттерн Наблюдатель
Паттерн Наблюдатель - это поведенческий паттерн проектирования, используемый для установления один-ко-многим зависимостей между объектами. Когда объект (называемый субъектом или наблюдаемым) изменяется, все его зависимости (называемые наблюдателями) уведомляются и обновляются автоматически. Этот паттерн позволяет достичь слабой связанности между субъектами и наблюдателями, обеспечивая тем самым их деклассирование и гибкость.
2. Характеристики и Преимущества паттерна Наблюдатель
Паттерн Наблюдатель обладает следующими характеристиками и преимуществами:
- Cлабая связь между субъектами и наблюдателями, где субъект не нужно знать конкретные детали реализации наблюдателей.
- Динамическое добавление и удаление наблюдателей, делая систему более гибкой.
- Cледует принципу открытости/закрытости между субъектами и наблюдателями, обеспечивая независимое расширение и возможность повторного использования.
- Cпособен установить один-ко-многим зависимость, где субъект может иметь несколько наблюдателей.
3. Примеры Практического Применения паттерна Наблюдатель
Паттерн Наблюдатель имеет множество практических применений в реальной жизни, таких как:
- Механизм обработки событий в графических пользовательских интерфейсах, например, обработка действий при нажатии кнопки.
- Отслеживание реального времени котировок на фондовом рынке.
- Уведомление о рекламных акциях на электронной коммерции.
4. Реализация паттерна Наблюдатель в Golang
4.1 UML-диаграмма классов
4.2 Введение в пример
В этом примере у нас есть субъект (Subject) и два наблюдателя (ObserverA и ObserverB). Субъект может регистрировать, удалять и уведомлять наблюдателей.
4.3 Шаги Реализации
4.3.1 Создание интерфейса субъекта и класса Конкретный Субъект
type Subject interface {
RegisterObserver(observer Observer)
RemoveObserver(observer Observer)
NotifyObservers()
}
type ConcreteSubject struct {
observers []Observer
}
// Регистрация объекта слушателя
func (subject *ConcreteSubject) RegisterObserver(observer Observer) {
subject.observers = append(subject.observers, observer)
}
// Удаление объекта слушателя
func (subject *ConcreteSubject) RemoveObserver(observer Observer) {
for i, obs := range subject.observers {
if obs == observer {
subject.observers = append(subject.observers[:i], subject.observers[i+1:]...)
break
}
}
}
// Триггер уведомления о событии
func (subject *ConcreteSubject) NotifyObservers() {
for _, observer := range subject.observers {
observer.Update()
}
}
4.3.2 Создание интерфейса наблюдателя и классов Конкретный Наблюдатель
type Observer interface {
Update()
}
type ConcreteObserverA struct {}
func (observer *ConcreteObserverA) Update() {
fmt.Println("Наблюдатель A уведомлен.")
}
type ConcreteObserverB struct {}
func (observer *ConcreteObserverB) Update() {
fmt.Println("Наблюдатель B уведомлен.")
}
4.4 Демонстрация Кода Примера
func main() {
subject := &ConcreteSubject{}
observerA := &ConcreteObserverA{}
observerB := &ConcreteObserverB{}
subject.RegisterObserver(observerA)
subject.RegisterObserver(observerB)
subject.NotifyObservers()
subject.RemoveObserver(observerA)
subject.NotifyObservers()
}
Вывод:
Наблюдатель A уведомлен.
Наблюдатель B уведомлен.
Наблюдатель B уведомлен.
Вышеприведенный пример демонстрирует конкретную реализацию паттерна наблюдателя. Субъект (ConcreteSubject) зарегистрировал двух наблюдателей (ObserverA и ObserverB), затем уведомил этих двух наблюдателей. После этого наблюдатель A был удален из субъекта, и оставшийся наблюдатель B был уведомлен снова.