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

观察者设计模式

观察者设计模式(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发布订阅

相关推荐
北冥有鱼-.7 分钟前
Java到底是值传递还是引用传递????
java·开发语言
u01472373011 分钟前
java中 如何从jar中读取资源文件?
java·jar
zx132312 分钟前
idea 修改项目参数, 不修改application.yaml文件
java·ide·intellij-idea
牧子与羊14 分钟前
idea下java的maven项目编译内存溢出GC overhead limit exceeded解决办法
java·maven·intellij-idea
YONG823_API16 分钟前
如何通过API实现淘宝商品评论数据抓取?item_review获取淘宝商品评论
大数据·开发语言·javascript·数据库·网络爬虫
Milk夜雨23 分钟前
初步认识UML
开发语言·uml
失眠的咕噜24 分钟前
vue 导出excel接口请求和axios返回值blob类型处理
前端·javascript·vue.js
hanbarger28 分钟前
面向对象分析和设计OOA/D,UML,GRASP
软件工程·uml
n北斗1 小时前
arr.length 和 string.length()
java
野生派蒙1 小时前
排序算法:冒泡排序
java·数据结构·算法·排序算法