Observer Pattern là một trong những design pattern thuộc nhóm Behavioral Patterns (mẫu hành vi), được sử dụng để tạo ra mối quan hệ phụ thuộc một-nhiều giữa các đối tượng. Khi một đối tượng thay đổi trạng thái, tất cả các đối tượng phụ thuộc của nó sẽ được thông báo và tự động cập nhật.
Cơ bản về Observer Pattern
Trong Observer Pattern, có hai thành phần chính:
- Subject (Chủ thể): Là đối tượng có thể thay đổi trạng thái. Khi trạng thái thay đổi, nó sẽ thông báo cho các Observer (người quan sát) đã đăng ký với nó.
- Observer (Người quan sát): Là các đối tượng muốn được thông báo khi trạng thái của Subject thay đổi. Mỗi khi Subject có sự thay đổi, các Observer sẽ tự động nhận được thông báo và thực hiện hành động phù hợp.
Khi nào nên sử dụng Observer Pattern?
Observer Pattern hữu ích trong các tình huống mà bạn muốn duy trì tính đồng bộ giữa các đối tượng, đặc biệt là khi có sự thay đổi trạng thái từ một nguồn duy nhất nhưng có nhiều thành phần khác nhau cần cập nhật theo.
Ví dụ phổ biến của Observer Pattern bao gồm:
- Ứng dụng GUI: Khi người dùng tương tác với một nút bấm hoặc sự kiện nào đó, nhiều phần của ứng dụng cần được thông báo để cập nhật giao diện.
- Mô hình sự kiện: Trong các hệ thống sự kiện, khi một sự kiện xảy ra, nhiều người nghe sự kiện (event listeners) cần được thông báo để xử lý.
Cách hoạt động của Observer Pattern
Quá trình làm việc của Observer Pattern có thể được mô tả qua các bước sau:
- Subject lưu giữ danh sách các Observer đã đăng ký theo dõi nó.
- Khi trạng thái của Subject thay đổi, nó sẽ gọi phương thức để thông báo cho tất cả các Observer trong danh sách.
- Mỗi Observer sẽ có phương thức riêng để cập nhật trạng thái dựa trên thông báo nhận được từ Subject.
Ví dụ mã minh họa Observer Pattern
// Interface Observer
public interface Observer {
void update(String message);
}
// Concrete Observer
public class ConcreteObserver implements Observer {
private String name;
public ConcreteObserver(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + " nhận thông báo: " + message);
}
}
// Interface Subject
public interface Subject {
void addObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
// Concrete Subject
import java.util.ArrayList;
import java.util.List;
public class ConcreteSubject implements Subject {
private List<Observer> observers = new ArrayList<>();
private String message;
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(message);
}
}
public void setMessage(String message) {
this.message = message;
notifyObservers();
}
}
// Sử dụng Observer Pattern
public class Main {
public static void main(String[] args) {
ConcreteSubject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver("Observer 1");
Observer observer2 = new ConcreteObserver("Observer 2");
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.setMessage("Trạng thái mới");
}
}
Phân tích mã ví dụ
- Observer là một interface, có phương thức
update
để các đối tượng có thể thực hiện hành động khi nhận được thông báo từ Subject.
- ConcreteObserver là một lớp cụ thể triển khai Observer, khi nhận thông báo, nó in ra thông điệp nhận được.
- Subject là một interface khác chứa các phương thức để quản lý danh sách Observer và thông báo cho họ.
- ConcreteSubject là lớp cụ thể triển khai Subject, giữ trạng thái và khi trạng thái thay đổi, nó gọi
notifyObservers
để gửi thông báo đến tất cả các Observer đã đăng ký.
- Trong hàm
main
, chúng ta tạo ra đối tượng Subject và đăng ký một vài Observer, sau đó thay đổi trạng thái của Subject và các Observer được thông báo về sự thay đổi đó.
Kết luận
Observer Pattern rất hữu ích trong các trường hợp cần một cơ chế cập nhật tự động giữa nhiều đối tượng phụ thuộc vào nhau. Nó giúp giảm thiểu sự kết nối chặt chẽ giữa các đối tượng, từ đó tăng tính linh hoạt và khả năng mở rộng của hệ thống.