设计模式—观察者模式与发布订阅

观察者设计模式

观察者设计模式(Observer Design Pattern)是一种常用的软件设计模式,它是一种行为型模式。该模式用于定义对象之间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知并自动更新。

结构

观察者模式通常涉及以下几个角色:

  1. Subject(主题):主题是被观察的对象,它包含了需要被观察的状态。当主题状态发生变化时,它会通知所有的观察者对象。

  2. Observer(观察者):观察者是依赖于主题的对象,它们将在主题状态发生变化时得到通知,并进行相应的更新操作。

  3. ConcreteSubject(具体主题):具体主题是主题的具体实现,它维护了一组观察者对象,并在状态发生改变时通知它们。

  4. ConcreteObserver(具体观察者):具体观察者实现了观察者接口,在收到主题通知时执行特定的更新操作。

示例

以下是一个简单的观察者模式的示例,假设我们有一个主题(Subject)代表气象站,而观察者(Observer)是一组天气显示板,它们会在气象站更新数据时自动更新显示:

复制代码
import java.util.ArrayList;
import java.util.List;

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

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

// 具体主题
class WeatherData implements Subject {
    private List<Observer> observers;
    private float temperature;
    private float humidity;
    private float pressure;

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

    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, 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();
    }
}

// 具体观察者
class CurrentConditionsDisplay implements Observer {
    private float temperature;
    private float humidity;

    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 WeatherStation {
    public static void main(String[] args) {
        WeatherData weatherData = new WeatherData();
        
        CurrentConditionsDisplay currentDisplay = new CurrentConditionsDisplay();
        
        weatherData.registerObserver(currentDisplay);
        
        weatherData.setMeasurements(80, 65, 30.4f);
    }
}

发布订阅者模式

发布-订阅者模式(Publish-Subscribe Pattern)是一种软件设计模式,用于实现消息的发布和订阅机制,也被称为观察者模式的变体。在发布-订阅者模式中,消息的发布者(发布者)和消息的接收者(订阅者)之间没有直接的依赖关系,它们通过一个称为"消息代理"或"事件总线"的中介来进行通信。这种模式允许组件之间松耦合地通信,从而提高系统的可扩展性和灵活性。

结构

发布-订阅者模式通常包括以下几个关键部分:

  1. 发布者(Publisher):负责发布消息或事件到消息代理。

  2. 订阅者(Subscriber):注册对特定类型的消息或事件感兴趣,并在消息到达时执行相应的操作。

  3. 消息代理(Message Broker):作为发布者和订阅者之间的中介,负责管理消息的路由和传递。它维护了发布者和订阅者之间的关系,并在消息到达时将消息传递给所有订阅者。

示例

以下是一个简单的发布-订阅者模式的示例,假设我们有一个新闻发布系统,包括新闻发布者和新闻订阅者:

复制代码
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// 消息代理
class MessageBroker {
    private Map<String, List<Subscriber>> topics = new HashMap<>();

    public void subscribe(String topic, Subscriber subscriber) {
        topics.computeIfAbsent(topic, k -> new ArrayList<>()).add(subscriber);
    }

    public void publish(String topic, String message) {
        List<Subscriber> subscribers = topics.get(topic);
        if (subscribers != null) {
            for (Subscriber subscriber : subscribers) {
                subscriber.receive(message);
            }
        }
    }
}

// 订阅者接口
interface Subscriber {
    void receive(String message);
}

// 新闻订阅者
class NewsSubscriber implements Subscriber {
    private String name;

    public NewsSubscriber(String name) {
        this.name = name;
    }

    public void receive(String message) {
        System.out.println(name + " received news: " + message);
    }
}

// 新闻发布者
class NewsPublisher {
    private MessageBroker messageBroker;

    public NewsPublisher(MessageBroker messageBroker) {
        this.messageBroker = messageBroker;
    }

    public void publishNews(String topic, String news) {
        messageBroker.publish(topic, news);
    }
}

// 测试
public class NewsSystem {
    public static void main(String[] args) {
        MessageBroker messageBroker = new MessageBroker();
        
        NewsPublisher publisher = new NewsPublisher(messageBroker);
        publisher.publishNews("sports", "New record set in 100m sprint!");
        publisher.publishNews("technology", "New smartphone announced!");
        
        NewsSubscriber subscriber1 = new NewsSubscriber("John");
        NewsSubscriber subscriber2 = new NewsSubscriber("Alice");
        
        messageBroker.subscribe("sports", subscriber1);
        messageBroker.subscribe("technology", subscriber2);
        
        publisher.publishNews("sports", "Team wins championship!");
    }
}

发布-订阅者模式在事件驱动的系统中非常有用,它可以使系统中的各个组件彼此解耦,并提供一种灵活的通信机制。

观察者vs发布订阅

相关推荐
七夜zippoe2 分钟前
缓存三大劫攻防战:穿透、击穿、雪崩的Java实战防御体系(二)
java·开发语言·缓存
古夕3 分钟前
前端文件下载的三种方式:a标签、Blob、ArrayBuffer
前端·javascript·vue.js
李李记5 分钟前
Node.js 打包踩坑?NCC+PKG 从单文件到多平台可执行文件,解决 axios 缺失等 80% 问题
javascript
大飞pkz10 分钟前
【设计模式】题目小练1
开发语言·设计模式·c#·题目小练
毕设源码-邱学长17 分钟前
【开题答辩全过程】以 博物馆参观预约管理系统为例,包含答辩的问题和答案
java·eclipse
郭庆汝40 分钟前
Windows安装java流程
java·windows·android studio
Yvonne爱编码1 小时前
后端编程开发路径:从入门到精通的系统性探索
java·前端·后端·python·sql·go
迦蓝叶1 小时前
JAiRouter 0.8.0 发布:Docker 全自动化交付 + 多架构镜像,一键上线不是梦
java·人工智能·网关·docker·ai·架构·自动化
im_AMBER1 小时前
Leetcode 18 java
java·算法·leetcode
Android技术之家1 小时前
Kotlin与Compose:Android开发的现代化变革
android·java·开发语言·kotlin