Java设计模式之观察者模式

观察者模式是一种行为设计模式,它允许一个对象(称为主题或可观察者)维护一系列依赖于它的对象(称为观察者),当主题的状态发生变化时,它会自动通知所有的观察者。这种模式被广泛应用于实现对象之间的松耦合,其中主题和观察者之间的关系是动态的。

观察者模式适用于以下场景:

1.事件处理和消息传递:当一个对象的状态发生变化,需要通知其他对象时,观察者模式非常有用。例如,GUI

应用程序中的按钮点击事件、数据更新事件等都可以使用观察者模式来处理。

2.发布-订阅机制:观察者模式是一种常见的发布-订阅机制的实现方式,其中发布者是观察者的主题,订阅者是观察者。当发布者发布新的消息或事件时,所有订阅者都会收到通知。

3.模型-视图-控制器(MVC)模式:在 MVC

模式中,模型通常充当主题,而视图是观察者。当模型的状态发生变化时,视图可以根据变化更新自身的显示。

4.实时数据更新:当需要在系统中实现实时数据更新时,观察者模式可以很好地满足这一需求。例如,股票市场中的股票价格变化、在线游戏中的玩家位置变化等。

5.异步编程:在异步编程中,观察者模式可以用来处理异步任务的完成通知。当异步任务完成时,观察者可以收到通知并执行相应的操作。

6.解耦对象之间的关系:观察者模式可以帮助降低对象之间的耦合度,使得对象之间的关系更加灵活。主题和观察者之间的关系是动态的,可以随时添加或移除观察者,而不会影响到主题和其他观察者之间的关系。

总的来说,观察者模式适用于任何涉及对象之间的一对多关系,其中一个对象的状态变化需要通知其他对象的情况。通过使用观察者模式,可以实现对象之间的松耦合,提高系统的可维护性和可扩展性。

下面根据一些常见场景一起来了解一下什么是观察者模式

事件处理和消息传递示例

首先我们定义一个事件

java 复制代码
// 定义事件
class Event {
    private String message;

    public Event(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

然后再定义一个事件处理器

java 复制代码
// 定义事件处理器
interface EventHandler {
    void handleEvent(Event event);
}

接着我们实现这个事件处理器

java 复制代码
// 具体的事件处理器
class ConcreteEventHandler implements EventHandler {
    private String name;

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

    @Override
    public void handleEvent(Event event) {
        System.out.println(name + " handles event: " + event.getMessage());
    }
}

最后我们需要一个总线来维护所有的事件处理器

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

// 事件总线
class EventBus {
    private List<EventHandler> eventHandlers = new ArrayList<>();

    // 注册事件处理器
    public void registerEventHandler(EventHandler eventHandler) {
        eventHandlers.add(eventHandler);
    }

    // 发布事件
    public void publishEvent(Event event) {
        for (EventHandler handler : eventHandlers) {
            handler.handleEvent(event);
        }
    }
}

测试一下

java 复制代码
public class Test {

    public static void main(String[] args) {
        // 创建事件总线
        EventBus eventBus = new EventBus();

        // 创建事件处理器
        EventHandler eventHandler1 = new ConcreteEventHandler("Event Handler 1");
        EventHandler eventHandler2 = new ConcreteEventHandler("Event Handler 2");

        // 注册事件处理器
        eventBus.registerEventHandler(eventHandler1);
        eventBus.registerEventHandler(eventHandler2);

        // 创建事件
        Event event = new Event("Sample Event");

        // 发布事件
        eventBus.publishEvent(event);
    }
}

运行结果

可以发现当事件发布时,所有注册的事件处理器都会收到通知,并处理相应的事件。

可能也有人发现了这不就是MQ吗,理论上来说这个的确是mq的一种简单实现方式,当然实际应用中我们一般会引用第三方框架比如RabbitMQ和SocketMQ等

发布-订阅机制示例

一样的还是先定义一个事件

java 复制代码
// 定义事件
class Event {
    private String message;

    public Event(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}

然后我们来一个消息订阅者

java 复制代码
// 定义订阅者
interface Subscriber {
    void receive(Event event);
}

实现订阅者具体操作

java 复制代码
// 具体订阅者
class ConcreteSubscriber implements Subscriber {
    private String name;

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

    @Override
    public void receive(Event event) {
        System.out.println(name + " received message: " + event.getMessage());
    }
}

我们还需要一个发布消息的人

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

// 定义发布者
class Publisher {
    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, Event event) {
        List<Subscriber> subscribers = topics.getOrDefault(topic, new ArrayList<>());
        for (Subscriber subscriber : subscribers) {
            subscriber.receive(event);
        }
    }
}

测试一下

java 复制代码
public class Test {

    public static void main(String[] args) {
        // 创建发布者
        Publisher publisher = new Publisher();

        // 创建订阅者
        Subscriber subscriber1 = new ConcreteSubscriber("Subscriber 1");
        Subscriber subscriber2 = new ConcreteSubscriber("Subscriber 2");
        Subscriber subscriber3 = new ConcreteSubscriber("Subscriber 3");

        // 订阅事件
        publisher.subscribe("topic1", subscriber1);
        publisher.subscribe("topic2", subscriber2);
        publisher.subscribe("topic2", subscriber3);

        // 发布事件
        publisher.publish("topic1", new Event("Message 1 for topic1"));
        publisher.publish("topic2", new Event("Message 2 for topic2"));
    }
}

运行结果

这个就更像MQ的消息队列模式了,我们可以将订阅者和消息队列绑定在一起,然后给不同的队列推送不同的事件由不同的订阅者去处理

相关推荐
从心归零13 分钟前
sshj使用代理连接服务器
java·服务器·sshj
IT毕设梦工厂1 小时前
计算机毕业设计选题推荐-在线拍卖系统-Java/Python项目实战
java·spring boot·python·django·毕业设计·源码·课程设计
Ylucius2 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
七夜zippoe2 小时前
分布式系统实战经验
java·分布式
是梦终空2 小时前
JAVA毕业设计176—基于Java+Springboot+vue3的交通旅游订票管理系统(源代码+数据库)
java·spring boot·vue·毕业设计·课程设计·源代码·交通订票
落落落sss3 小时前
sharding-jdbc分库分表
android·java·开发语言·数据库·servlet·oracle
码爸3 小时前
flink doris批量sink
java·前端·flink
Monodye3 小时前
【Java】网络编程:TCP_IP协议详解(IP协议数据报文及如何解决IPv4不够的状况)
java·网络·数据结构·算法·系统架构
一丝晨光3 小时前
逻辑运算符
java·c++·python·kotlin·c#·c·逻辑运算符
无名指的等待7124 小时前
SpringBoot中使用ElasticSearch
java·spring boot·后端