Observer Design Pattern – Trợ thủ đắc lực của Developers

Nhìn vào tên “Observer Design Pattern”, bạn có thể nhanh chóng đoán ra rằng mẫu thiết kế này liên quan đến việc quan sát và theo dõi. Nhưng thực sự, Observer Pattern cung cấp nhiều hơn những điều đó. Nó là một mẫu thiết kế thuộc nhóm Behavioral Pattern, cho phép các đối tượng thông báo và cập nhật tự động khi trạng thái của một đối tượng khác thay đổi.

Kiến trúc của Observer Pattern

Observer Design Pattern
Hình ảnh chỉ kiến trúc của Observer Design Pattern.

Trong mô hình này, có các thành phần quan trọng sau:

  • Publisher (subject): Đây là lớp cần lắng nghe. Khi có sự kiện, Publisher sẽ thông báo tới Subscriber (observer).
  • Subscriber: Được sử dụng để các Publisher báo cáo mỗi khi có sự kiện xảy ra.
  • ConcreteSubscriber: Cài đặt cụ thể hành động mà lớp cần thực hiện khi nhận được sự kiện từ Publisher.

Ưu điểm và nhược điểm

Ưu điểm của Observer Pattern

  • Dễ mở rộng: Observer Pattern cho phép ta thay đổi Subject và Observer một cách độc lập. Ta có thể tái sử dụng các Subject mà không cần sửa đổi các Observer, và ngược lại.
  • Xác lập mối quan hệ trong thời gian chạy: Sự thay đổi trong 1 đối tượng có thể được thông báo đến các đối tượng khác mà không cần chúng liên kết mật thiết với nhau.
  • Không giới hạn số lượng Observer: Ta có thể có bao nhiêu Observer tùy ý.

Nhược điểm của Observer Pattern

  • Cập nhật không đồng bộ: Vì các Observer không nhận biết sự tồn tại của nhau, điều này có thể khiến việc thay đổi Subject mất nhiều công sức.
  • Thứ tự cập nhật ngẫu nhiên của Subscriber: Khi có sự kiện xảy ra, Subscriber sẽ được thông báo theo thứ tự ngẫu nhiên.

Khi nào sử dụng Observer Pattern?

Observer Pattern được sử dụng khi:

  • Cần thông báo sự thay đổi trạng thái từ 1 đối tượng đến các đối tượng khác mà không cần giữ chúng liên kết mật thiết với nhau.
  • Muốn mở rộng dự án mà ít thay đổi nhất.
  • Trong trường hợp một đối tượng yêu cầu thay đổi đến các đối tượng khác, nhưng ta không biết số lượng đối tượng cần thay đổi là bao nhiêu.
  • Khi một đối tượng thông báo các đối tượng khác mà không cần biết về danh tính của đối tượng đó.

Ví dụ với nhóm ngôn ngữ C

Hãy xem ví dụ dưới đây với ngôn ngữ C# để hiểu rõ hơn về Observer Pattern:

public interface IObserver {
    void Update(ISubject subject);
}

public interface ISubject {
    void Attach(IObserver observer);
    void Detach(IObserver observer);
    void Notify();
}

public class Subject : ISubject {
    public int State { get; set; } = -0;
    private List _observers = new List();

    public void Attach(IObserver observer) {
        Console.WriteLine("Subject: Đã gắn kết một Observer.");
        this._observers.Add(observer);
    }

    public void Detach(IObserver observer) {
        this._observers.Remove(observer);
        Console.WriteLine("Subject: Đã hủy gắn kết một Observer.");
    }

    public void Notify() {
        Console.WriteLine("Subject: Đang thông báo cho các Observer...");
        foreach (var observer in _observers) {
            observer.Update(this);
        }
    }

    public void SomeBusinessLogic() {
        Console.WriteLine("Subject: Đang thực hiện một nhiệm vụ quan trọng.");
        this.State = new Random().Next(0, 10);
        Thread.Sleep(15);
        Console.WriteLine("Subject: Trạng thái của tôi đã thay đổi thành: " + this.State);
        this.Notify();
    }
}

class ConcreteObserverA : IObserver {
    public void Update(ISubject subject) {
        if ((subject as Subject).State < 3) {
            Console.WriteLine("ConcreteObserverA: Đã phản ứng với sự kiện.");
        }
    }
}

class ConcreteObserverB : IObserver {
    public void Update(ISubject subject) {
        if ((subject as Subject).State == 0 || (subject as Subject).State >= 2) {
            Console.WriteLine("ConcreteObserverB: Đã phản ứng với sự kiện.");
        }
    }
}

class Program {
    static void Main(string[] args) {
        var subject = new Subject();
        var observerA = new ConcreteObserverA();
        subject.Attach(observerA);
        var observerB = new ConcreteObserverB();
        subject.Attach(observerB);

        subject.SomeBusinessLogic();

        subject.Detach(observerB);
        subject.SomeBusinessLogic();
    }
}

Kết luận

Observer Pattern là một công cụ quan trọng không thể thiếu trong công việc của Developers. Nó giúp tạo ra các đối tượng linh hoạt và khả năng mở rộng nhanh chóng. Bằng cách áp dụng Observer Pattern, ta có thể tận dụng tối đa tác động của một sự kiện trên hệ thống của mình.

Hy vọng với bài viết này, các bạn đã hiểu rõ hơn về Observer Pattern và ứng dụng của nó trong lĩnh vực phát triển. Đừng quên theo dõi các bài viết khác về Design Patterns – trợ thủ đắc lực của Developers của chúng tôi!

Tài liệu tham khảo:

[1] Refactoring.Guru. https://refactoring.guru/design-patterns
[2] Design Patterns for Dummies, Steve Holzner, PhD
[3] Head First, Eric Freeman
[4] Gang of Four Design Patterns 4.0
[5] Dive into Design Pattern

FEATURED TOPIC