Skip to main content

Command Palette

Search for a command to run...

Hướng dẫn Observer Pattern trong Java

Published
5 min readView as Markdown

1. Giới thiệu Observer Pattern

Observer Pattern là một mẫu thiết kế thuộc nhóm Behavioral Patterns, được sử dụng để định nghĩa một sự phụ thuộc một-nhiều giữa các đối tượng, sao cho 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ó đều được thông báo và cập nhật tự động. Observer Pattern giúp tách biệt giữa đối tượng quan sát và đối tượng quan sát, tăng tính linh hoạt và khả năng mở rộng của hệ thống.

2. Các trường hợp ứng dụng Observer Pattern

  • Hệ thống sự kiện: Khi cần xây dựng hệ thống sự kiện, nơi một sự kiện có thể kích hoạt nhiều hành động khác nhau.

  • Mô hình MVC: Khi cần thông báo các thay đổi từ model đến view trong mô hình MVC.

  • Cập nhật dữ liệu thời gian thực: Khi cần cập nhật dữ liệu thời gian thực giữa nhiều thành phần trong hệ thống.

3. Triển khai Observer Pattern

3.1. Ví dụ triển khai đơn giản

Giả sử chúng ta có một đối tượng Subject có thể thay đổi trạng thái và các đối tượng Observer sẽ được thông báo khi trạng thái thay đổi.

import java.util.ArrayList;
import java.util.List;

// Bước 1: Tạo interface Observer
public interface Observer {
    void update();
}

// Bước 2: Tạo lớp Subject
public class Subject {
    private List<Observer> observers = new ArrayList<>();
    private int state;

    public int getState() {
        return state;
    }

    public void setState(int state) {
        this.state = state;
        notifyAllObservers();
    }

    public void attach(Observer observer) {
        observers.add(observer);
    }

    public void notifyAllObservers() {
        for (Observer observer : observers) {
            observer.update();
        }
    }
}

// Bước 3: Tạo các lớp Observer cụ thể
public class BinaryObserver implements Observer {
    private Subject subject;

    public BinaryObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("Binary String: " + Integer.toBinaryString(subject.getState()));
    }
}

public class HexaObserver implements Observer {
    private Subject subject;

    public HexaObserver(Subject subject) {
        this.subject = subject;
        this.subject.attach(this);
    }

    @Override
    public void update() {
        System.out.println("Hex String: " + Integer.toHexString(subject.getState()));
    }
}

// Bước 4: Sử dụng Observer Pattern
public class ObserverPatternDemo {
    public static void main(String[] args) {
        Subject subject = new Subject();

        new BinaryObserver(subject);
        new HexaObserver(subject);

        System.out.println("First state change: 15");
        subject.setState(15);

        System.out.println("Second state change: 10");
        subject.setState(10);
    }
}

3.2. Ví dụ triển khai phức tạp

Giả sử chúng ta có một hệ thống quản lý thông báo thời tiết. Khi dữ liệu thời tiết thay đổi, hệ thống sẽ thông báo đến các màn hình hiển thị khác nhau.

import java.util.ArrayList;
import java.util.List;

// Bước 1: Tạo interface Observer
public interface Observer {
    void update(float temperature, float humidity, float pressure);
}

// Bước 2: Tạo lớp Subject
public class WeatherData {
    private List<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

    public WeatherData() {
        observers = new ArrayList<>();
    }

    public void registerObserver(Observer o) {
        observers.add(o);
    }

    public void removeObserver(Observer o) {
        observers.remove(o);
    }

    public void notifyObservers() {
        for (Observer observer : observers) {
            observer.update(temperature, humidity, pressure);
        }
    }

    public void measurementsChanged() {
        notifyObservers();
    }

    public void setMeasurements(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        this.pressure = pressure;
        measurementsChanged();
    }
}

// Bước 3: Tạo các lớp Observer cụ thể
public class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;

    public CurrentConditionsDisplay(WeatherData weatherData) {
        weatherData.registerObserver(this);
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        this.temperature = temperature;
        this.humidity = humidity;
        display();
    }

    public void display() {
        System.out.println("Current conditions: " + temperature + "F degrees and " + humidity + "% humidity");
    }
}

public class ForecastDisplay implements Observer {
    private float currentPressure = 29.92f;
    private float lastPressure;

    public ForecastDisplay(WeatherData weatherData) {
        weatherData.registerObserver(this);
    }

    @Override
    public void update(float temperature, float humidity, float pressure) {
        lastPressure = currentPressure;
        currentPressure = pressure;
        display();
    }

    public void display() {
        System.out.println("Forecast: ");
        if (currentPressure > lastPressure) {
            System.out.println("Improving weather on the way!");
        } else if (currentPressure == lastPressure) {
            System.out.println("More of the same");
        } else if (currentPressure < lastPressure) {
            System.out.println("Watch out for cooler, rainy weather");
        }
    }
}

// Bước 4: Sử dụng Observer Pattern
public class WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();

        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay(weatherData);
        ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);

        weatherData.setMeasurements(80, 65, 30.4f);
        weatherData.setMeasurements(82, 70, 29.2f);
        weatherData.setMeasurements(78, 90, 29.2f);
    }
}

4. Phân tích các trường hợp ứng dụng Observer Pattern

4.1. Hệ thống sự kiện

  • Ưu điểm: Giúp xây dựng hệ thống sự kiện linh hoạt, nơi một sự kiện có thể kích hoạt nhiều hành động khác nhau.

  • Nhược điểm: Cần quản lý tốt việc đăng ký và hủy đăng ký Observer để tránh rò rỉ bộ nhớ.

4.2. Mô hình MVC

  • Ưu điểm: Giúp thông báo các thay đổi từ model đến view một cách hiệu quả, đảm bảo rằng view luôn cập nhật trạng thái mới nhất của model.

  • Nhược điểm: Cần thiết kế và triển khai đúng cách để đảm bảo tính nhất quán và tránh các vòng lặp thông báo.

4.3. Cập nhật dữ liệu thời gian thực

  • Ưu điểm: Giúp cập nhật dữ liệu thời gian thực giữa nhiều thành phần trong hệ thống, đảm bảo rằng tất cả các thành phần đều có dữ liệu mới nhất.

  • Nhược điểm: Cần kiểm soát tần suất thông báo để tránh ảnh hưởng đến hiệu suất của hệ thống.

5. Kết luận

Observer Pattern là một mẫu thiết kế mạnh mẽ và linh hoạt, giúp xây dựng các hệ thống có khả năng thông báo và cập nhật tự động khi có sự thay đổi trong trạng thái của đối tượng. Việc hiểu và áp dụng đúng Observer Pattern sẽ giúp lập trình viên xây dựng các hệ thống dễ bảo trì, dễ mở rộng và hiệu quả hơn.

More from this blog

hoangkim

366 posts