网站关键词排名优化,wordpress the7 模板,2345浏览器网站大全,北京地区网站制作公司观察者模式和订阅模式在概念上是相似的#xff0c;它们都涉及到一个对象#xff08;通常称为“主题”或“发布者”#xff09;和多个依赖对象#xff08;称为“观察者”或“订阅者”#xff09;之间的关系。然而#xff0c;尽管它们有相似之处#xff0c;但在某些方面也…观察者模式和订阅模式在概念上是相似的它们都涉及到一个对象通常称为“主题”或“发布者”和多个依赖对象称为“观察者”或“订阅者”之间的关系。然而尽管它们有相似之处但在某些方面也存在细微的差别。
观察者模式Observer Pattern
核心思想
定义对象间的一种一对多的依赖关系使得每当一个对象改变状态则所有依赖于它的对象都会得到通知并自动更新。
结构
通常包括主题Subject和观察者Observer两个主要角色。主题维护一个观察者列表当状态变化时通知列表中的所有观察者。
实现方式
观察者模式可以通过在主题中维护一个观察者列表并提供注册addObserver和注销removeObserver观察者的方法来实现。当主题状态变化时遍历观察者列表并调用每个观察者的更新方法。
应用场景
常用于事件处理系统、GUI工具包中的事件监听器、订阅-发布系统等。
Demo
设计一个天气预报系统当天气变化时通知多个订阅了天气预报的用户。
定义 Subject 接口
Subject接口被观察者代表被观察的对象定义注册新观察者移除观察者和通知观察者三个接口。
package org.example.observer;import java.util.Observer;public interface MySubject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}实现 Subject 接口
储存观察者列表被观察对象变化信息通知观察者列表
package org.example.observer;import java.util.ArrayList;
import java.util.List;public class WeatherStation implements MySubject {private ListMyObserver observers;private String weather;public WeatherStation() {observers new ArrayListMyObserver();}Overridepublic void registerObserver(MyObserver o) {this.observers.add(o);}Overridepublic void removeObserver(MyObserver o) {this.observers.remove(o);}Overridepublic void notifyObservers() {this.observers.forEach(observer - observer.update(weather));}public void setWeather(String weather) {this.weather weather;notifyObservers();}
}
定义 Observer 接口
Observer接口代表观察者定义接收到通知后需要执行的动作接口
package org.example.observer;public interface MyObserver {void update(String weather);
}实现 Observer 接口
观察者接收到通知后实现具体要执行的动作
package org.example.observer;public class User implements MyObserver {private String name;public User(String name) {this.name name;}Overridepublic void update(String weather) {System.out.println(String.format(name %s receive weather update : %s, name, weather));}
}
测试
package org.example.observer;public class MyObserverMain {public static void main(String[] args) {// 创建被观察者对象WeatherStation station new WeatherStation();// 创建观察者对象User userA new User(A);User userB new User(B);User userC new User(C);// 注册观察者并更新天气station.registerObserver(userA);station.registerObserver(userB);station.registerObserver(userC);station.setWeather(Sunny);// 移除部分观察者再次更新天气station.removeObserver(userA);station.setWeather(Rainy);}
} 订阅模式Subscription Pattern
核心思想
也是一种一对多的关系但更强调“订阅”的概念。订阅者订阅某个主题或频道以接收该主题或频道发布的更新或消息。
结构
通常包括发布者Publisher、订阅者Subscriber和消息Message三个主要角色。订阅者通过订阅某个发布者来接收其发布的消息。
实现方式
订阅模式可以通过事件总线Event Bus、消息队列Message Queue或专门的订阅系统来实现。订阅者可以订阅特定的主题或频道并接收该主题或频道发布的消息。
应用场景
广泛用于消息传递系统、事件驱动架构、分布式系统中的服务间通信等。
Demo
定义消息类
package org.example.publish_subscriber;public class Message {private String content;public Message(String content) {this.content content;}public String getContent() {return content;}
}
定义订阅者接口
package org.example.publish_subscriber;public interface Subscriber {void receive(String message);
}
实现订阅者接口
package org.example.publish_subscriber;public class User implements Subscriber{private String name;public User(String name) {this.name name;}Overridepublic void receive(String message) {System.out.println(String.format(%s received message: %s, name, message));}
}
定义事件总线
package org.example.publish_subscriber;import java.util.Map;
import java.util.concurrent.*;public class EventBus {private final MapSubscriber, BlockingQueueMessage subscriberQueues new ConcurrentHashMap();private final ExecutorService executor Executors.newCachedThreadPool();private volatile boolean running true;public void subscriber(Subscriber subscriber) {BlockingQueueMessage queue new LinkedBlockingQueue();subscriberQueues.put(subscriber, queue);executor.submit(() - {try {while (running || !queue.isEmpty()) {Message message queue.take();subscriber.receive(message);}} catch (Exception e) {Thread.currentThread().interrupt();}});}public void publish(Message message) {subscriberQueues.values().forEach(queue - {try {queue.put(message);} catch (InterruptedException e) {Thread.currentThread().interrupt();}});}public void shutdown() {running false;executor.shutdown();try {if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {executor.shutdownNow();}} catch (InterruptedException e) {executor.shutdownNow();Thread.currentThread().interrupt();}}
}
测试
package org.example.publish_subscriber;public class PubSubMain {public static void main(String[] args) throws InterruptedException {EventBus eventBus new EventBus();User userA new User(A);User userB new User(B);User userC new User(C);User userD new User(D);eventBus.subscriber(userA);eventBus.subscriber(userB);eventBus.subscriber(userC);eventBus.subscriber(userD);for (int i 0; i 10; i) {eventBus.publish(new Message(i Hello World!));eventBus.publish(new Message(i Hello Shore!));}Thread.sleep(10000);eventBus.shutdown();}
} 在上面的例子中executor.submit 被用于提交订阅者线程的任务。每个订阅者都有一个对应的工作队列当发布消息时消息会被放入每个订阅者的工作队列中。订阅者线程会不断地从自己的工作队列中取出消息并处理。通过这种方式实现了发布-订阅模式中的异步通信和消息分发
区别与联系
区别
观察者模式更侧重于对象间的依赖关系和状态变化的通知机制而订阅模式更强调消息的传递和订阅-发布的关系。此外观察者模式通常是在单个应用或系统内使用而订阅模式可能涉及跨系统或跨网络的消息传递。
联系
两者都涉及到一个对象主题/发布者和多个依赖对象观察者/订阅者之间的关系且都实现了某种形式的通知机制。在某些情况下它们可以相互替代或结合使用。例如在一个分布式系统中可以使用订阅模式来实现不同服务之间的消息传递而在服务内部则可以使用观察者模式来实现状态变化的通知和更新。