观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都会得到通知并自动更新。观察者模式也被称为发布-订阅模式。

结构

  • 主题(Subject): 维护一组观察者对象,提供注册和删除观察者的接口,以及通知观察者的方法。
public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}
  • 具体主题(Concrete Subject): 实现主题接口,维护观察者列表,并在状态变化时通知观察者。
public class ConcreteSubject implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private int state;

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

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

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

    public void setState(int state) {
        this.state = state;
        notifyObservers();
    }
}
  • 观察者(Observer): 定义了一个更新方法,用于接收主题的通知。
public interface Observer {
    void update(int state);
}
  • 具体观察者(Concrete Observer): 实现观察者接口,用于处理主题的通知。
public class ConcreteObserver implements Observer {
    private int observerState;

    public void update(int state) {
        observerState = state;
        System.out.println("Observer updated with state: " + observerState);
    }
}

优点和缺点

优点:

  1. 松耦合: 观察者模式实现了主题和观察者之间的松耦合关系,主题不需要知道观察者的具体细节。
  2. 可扩展性: 可以很容易地增加或删除观察者,而不会影响主题的代码。
  3. 通知机制: 主题状态的变化会自动通知所有的观察者,确保观察者与主题状态保持同步。

缺点:

  1. 可能导致性能问题: 如果观察者很多,同时主题频繁变化,可能会导致性能问题。
  2. 可能引入循环依赖: 如果不小心设计,可能会出现观察者之间的循环依赖。

示例

以下是一个观察者模式的示例,模拟了一个气象站,主题对象为气象数据,观察者对象为显示器和日志记录器。

// 主题接口
public interface Subject {
    void registerObserver(Observer observer);
    void removeObserver(Observer observer);
    void notifyObservers();
}

// 具体主题 - 气象数据
public class WeatherData implements Subject {
    private List<Observer> observers = new ArrayList<>();
    private float temperature;

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

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

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

    public void setTemperature(float temperature) {
        this.temperature = temperature;
        notifyObservers();
    }
}

// 观察者接口
public interface Observer {
    void update(float temperature);
}

// 具体观察者 - 显示器
public class Display implements Observer {
    public void update(float temperature) {
        System.out.println("Display: Temperature is " + temperature);
    }
}

// 具体观察者 - 日志记录器
public class Logger implements Observer {
    public void update(float temperature) {
        System.out.println("Logger: Logging temperature data: " + temperature);
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        Observer display = new Display();
        Observer logger = new Logger();

        weatherData.registerObserver(display);
        weatherData.registerObserver(logger);

        weatherData.setTemperature(25.5f); // 触发观察者更新
    }
}

在这个示例中,WeatherData 是具体主题,维护观察者列表,当温度数据发生变化时,会通知所有观察者。Display 和 Logger 分别是具体观察者,它们实现了 Observer 接口,当收到通知时,会更新显示温度或记录温度日志。客户端代码创建了主题和观察者对象,并将观察者注册到主题上,当温度发生变化时,观察者会被自动通知。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注