1. Observer Pattern là gì

Mẫu Observer là một mẫu thiết kế hành vi được sử dụng để thiết lập mối quan hệ một-nhiều giữa các đối tượng. Cụ thể, khi một đối tượng (được gọi là subject hoặc observable) thay đổi, tất cả các đối tượng phụ thuộc của nó (được gọi là observers) sẽ được thông báo và cập nhật tự động. Mẫu này cho phép mối quan hệ lỏng lẻo giữa subjects và observers, do đó đạt được sự không kết nối và linh hoạt giữa các đối tượng.

2. Đặc điểm và Ưu điểm của Mẫu Observer

Mẫu Observer có các đặc điểm và ưu điểm sau:

  • Mối quan hệ lỏng lẻo giữa subjects và observers, trong đó subject không cần phải biết chi tiết cụ thể về cách triển khai của observers.
  • Có thể thêm và xóa observers động, làm cho hệ thống linh hoạt hơn.
  • Tuân theo nguyên lý mở-đóng giữa subjects và observers, cho phép mở rộng và tái sử dụng độc lập.
  • Có thể thiết lập mối quan hệ một-nhiều, trong đó một subject có thể có nhiều observers.

3. Ví dụ về Ứng dụng Thực tế của Mẫu Observer

Mẫu Observer có nhiều ứng dụng thực tế trong cuộc sống, chẳng hạn như:

  • Cơ chế xử lý sự kiện trong giao diện GUI, như xử lý hành động khi một nút được nhấn.
  • Thông báo về bảng giá chứng khoán thời gian thực.
  • Thông báo về các hoạt động khuyến mãi trên các nền tảng thương mại điện tử.

4. Triển khai của Mẫu Observer trong Golang

4.1 Sơ đồ Lớp UML

Mẫu Observer trong Golang

4.2 Giới thiệu Ví dụ

Trong ví dụ này, chúng ta có một subject (Subject) và hai observers (ObserverA và ObserverB). Subject có thể đăng ký, hủy đăng ký và thông báo cho observers.

4.3 Bước Triển khai

4.3.1 Tạo Interface Subject và Lớp Concrete Subject

type Subject interface {
    RegisterObserver(observer Observer)
    RemoveObserver(observer Observer)
    NotifyObservers()
}

type ConcreteSubject struct {
    observers []Observer
}

// Đăng ký đối tượng lắng nghe
func (subject *ConcreteSubject) RegisterObserver(observer Observer) {
    subject.observers = append(subject.observers, observer)
}

// Hủy đối tượng lắng nghe
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
        }
    }
}

// Kích hoạt thông báo sự kiện
func (subject *ConcreteSubject) NotifyObservers() {
    for _, observer := range subject.observers {
        observer.Update()
    }
}

4.3.2 Tạo Interface Observer và Lớp Concrete Observer

type Observer interface {
    Update()
}

type ConcreteObserverA struct {}

func (observer *ConcreteObserverA) Update() {
    fmt.Println("Observer A được thông báo.")
}

type ConcreteObserverB struct {}

func (observer *ConcreteObserverB) Update() {
    fmt.Println("Observer B được thông báo.")
}

4.4 Mã Thực hiện Ví dụ

func main() {
    subject := &ConcreteSubject{}
    observerA := &ConcreteObserverA{}
    observerB := &ConcreteObserverB{}

    subject.RegisterObserver(observerA)
    subject.RegisterObserver(observerB)

    subject.NotifyObservers()

    subject.RemoveObserver(observerA)

    subject.NotifyObservers()
}

Kết quả:

Observer A được thông báo
Observer B được thông báo
Observer B được thông báo

Mã ví dụ trên thể hiện cách triển khai cụ thể của mẫu Observer. Subject (ConcreteSubject) đã đăng ký hai observers (ObserverA và ObserverB), sau đó thông báo cho hai observers này. Sau đó, observer A đã bị hủy đăng ký từ subject và observer còn lại B lại được thông báo lần nữa.