网站搭建思路,二级域名网站可以做360推广,如何制作推广网站,wordpress提示没有权限观察者模式#xff08;Observer Pattern#xff09;是一种行为设计模式#xff0c;它定义了一种一对多的依赖关系#xff0c;让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时#xff0c;会通知所有观察者对象#xff0c;使它们能够自动更新。
一…
观察者模式Observer Pattern是一种行为设计模式它定义了一种一对多的依赖关系让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时会通知所有观察者对象使它们能够自动更新。
一、核心思想
观察者模式的核心思想是解耦主题被观察者和观察者使得它们可以独立变化而不会相互影响。这有助于降低对象之间的耦合度提高系统的可扩展性和可维护性。
二、定义与结构
1. 定义
观察者模式定义了对象之间的一种一对多依赖关系使得每当一个对象状态发生改变时其相关依赖对象皆得到通知并被自动更新。
2. 结构
Subject主题也称为被观察者它是一个接口或者抽象类定义了添加、删除和通知观察者的方法。它维护了一个观察者列表当自身状态发生变化时通过遍历这个列表来通知所有的观察者。ConcreteSubject具体主题实现了Subject接口它包含了一些可以被观察的状态属性并且在这些状态发生变化时负责调用通知方法来通知观察者。Observer观察者也是一个接口或者抽象类它定义了一个更新方法用于在收到主题通知时更新自己的状态。ConcreteObserver具体观察者实现了Observer接口它包含了用于存储自身状态的属性并且实现了更新方法在更新方法中根据主题传递过来的信息更新自己的状态。
三、角色
1. 主题Subject
职责是管理观察者对象的引用列表提供添加和删除观察者的方法。当自身状态发生变化时负责通知所有已注册的观察者。
2. 观察者Observer
定义了一个更新接口当收到主题的通知时会调用这个更新接口来更新自己的状态。
四、实现步骤及代码示例
1. 定义观察者接口
// 观察者接口
public interface Observer {void update(String news);
}2. 定义主题接口
import java.util.ArrayList;
import java.util.List;// 主题接口
public interface Subject {void attach(Observer observer);void detach(Observer observer);void notifyObservers(String news);
}3. 实现具体主题类
import java.util.ArrayList;
import java.util.List;// 具体主题类
public class NewsPublisher implements Subject {private ListObserver observers new ArrayList();private String latestNews;Overridepublic void attach(Observer observer) {observers.add(observer);}Overridepublic void detach(Observer observer) {observers.remove(observer);}Overridepublic void notifyObservers(String news) {this.latestNews news;for (Observer observer : observers) {observer.update(latestNews);}}
}4. 实现具体观察者类
// 具体观察者类
public class NewsSubscriber implements Observer {private String name;public NewsSubscriber(String name) {this.name name;}Overridepublic void update(String news) {System.out.println(name received news: news);}
}5. 测试代码
public class Main {public static void main(String[] args) {NewsPublisher publisher new NewsPublisher();NewsSubscriber subscriber1 new NewsSubscriber(Subscriber 1);NewsSubscriber subscriber2 new NewsSubscriber(Subscriber 2);publisher.attach(subscriber1);publisher.attach(subscriber2);publisher.notifyObservers(New technology released!);}
}五、常见技术框架应用
1、Vue 2 数据劫持
在Vue 2中观察者模式是通过Object.defineProperty()方法实现的这允许Vue能够追踪数据对象属性的变化并在变化发生时触发相应的更新。以下是对Vue 2中基于Object.defineProperty()实现的观察者模式的详细解析
1.1. 数据劫持
Vue 2 使用Object.defineProperty()来对数据对象的属性进行劫持。这个方法允许我们定义一个对象属性的getter和setter函数当属性被访问或修改时这些函数会被调用。
Object.defineProperty(obj, property, {get: function() {// 当属性被访问时执行的代码},set: function(newValue) {// 当属性被修改时执行的代码}
});在Vue中当数据对象被创建时Vue会使用Object.defineProperty()遍历对象的所有属性并为它们设置getter和setter。这样当这些属性在将来被访问或修改时Vue就能够感知到。
1.2. 依赖收集
在getter函数中Vue会进行依赖收集。所谓依赖收集就是当某个属性被访问时Vue会记录下当前正在执行的Watcher观察者。Watcher是Vue内部用于追踪数据变化的机制它会在数据变化时触发相应的更新。
当组件渲染或计算属性被计算时它们会访问数据对象的属性这时getter函数就会被调用Vue就会记录下当前的Watcher。
1.3. 派发更新
在setter函数中当数据属性被修改时Vue会触发setter函数。在这个函数中Vue会遍历之前收集的依赖Watcher并通知它们数据已经发生了变化需要重新执行以更新视图或计算属性。
1.4. 观察者Watcher
Watcher是Vue内部的一个类它用于追踪数据的变化并在数据变化时执行相应的回调函数。在Vue中Watcher有三种类型
渲染Watcher与组件的渲染函数相关联当数据变化时它会重新渲染组件。计算属性Watcher与计算属性相关联当计算属性的依赖数据变化时它会重新计算计算属性的值。侦听器Watcher通过vm.$watch方法创建的Watcher用于在数据变化时执行特定的回调函数。
1.5. 实现细节
Vue 2的内部实现非常复杂但基于上述原理我们可以简化地理解其观察者模式的实现过程
初始化数据使用Object.defineProperty()为数据对象的每个属性设置getter和setter。依赖收集在getter函数中检查当前是否存在活动的Watcher通常是在组件渲染或计算属性计算时如果存在则将其添加到该属性的依赖列表中。派发更新在setter函数中当属性值发生变化时遍历该属性的依赖列表并通知每个依赖Watcher数据已经变化需要执行更新操作。
1.6. 注意事项
由于Object.defineProperty()只能对对象的已有属性进行劫持因此Vue无法检测到对象属性的添加或删除。为了解决这个问题Vue提供了Vue.set()和Vue.delete()方法。深度监听默认情况下Vue只监听对象的第一层属性的变化。如果需要监听嵌套对象的变化可以在创建Vue实例时通过observe选项开启深度监听但请注意性能开销。然而在Vue 2中深度监听通常是通过递归地为嵌套对象设置getter和setter来实现的而不是简单地通过observe选项。实际上observe选项在Vue 2中并不直接控制深度监听。响应式系统的局限性由于JavaScript的限制和性能考虑Vue的响应式系统有一些局限性。例如它不能检测数组元素通过索引的直接修改或对象属性的添加/删除除非使用Vue.set()/Vue.delete()。
综上所述Vue 2通过Object.defineProperty()实现了观察者模式使得Vue能够追踪数据对象属性的变化并在变化发生时自动更新视图。然而由于JavaScript的限制和性能考虑Vue的响应式系统有一些局限性需要注意。
2. JavaScript 中 事件监听
// 创建一个按钮元素
const button document.createElement(button);
button.textContent Click me;// 定义观察者函数事件处理函数
const observerFunction function () {console.log(Button was clicked!);
};// 主题按钮添加观察者事件监听
button.addEventListener(click, observerFunction);// 将按钮添加到文档中
document.body.appendChild(button);在这个JavaScript示例中button是主题observerFunction是观察者。当按钮被点击主题状态改变时会触发观察者函数这类似于观察者模式的通知机制。
六、应用场景
当一个对象的改变需要同时改变其他对象而不知道具体有多少个对象有待改变时。
当一个抽象模型有两个方面其中一个方面依赖于另一方面这时可以通过观察者模式将这两者封装在独立的对象中以使它们各自独立地改变和复用。
当对一个对象的改变需要广播到其他对象时。观察者模式广泛应用于各种需要通知多个对象进行同步更新的场合包括但不限于
GUI事件监听机制在图形用户界面编程中按钮、文本框等控件的事件处理通常使用观察者模式。数据模型与视图同步在MVC架构中观察者模式常用于数据模型和视图之间的更新同步。发布-订阅系统观察者模式是发布-订阅系统的基础允许不同的服务订阅某个主题并接收通知。股票价格监控在金融系统中观察者模式可以让股票价格的变化自动通知所有依赖该数据的系统。社交媒体的通知机制当用户发布新动态时所有关注者都会收到通知。
七、优缺点
优点
解耦性高主题和观察者之间是松耦合的关系。主题只需要知道观察者实现了更新方法而不需要了解观察者的具体细节。这样可以方便地添加、删除和替换观察者同时也使得主题和观察者可以独立地进行修改和扩展。支持广播通信主题可以同时通知多个观察者使得系统能够方便地实现一对多的消息传递机制提高了信息传播的效率。
缺点
可能导致性能问题如果观察者数量过多当主题状态发生变化时通知所有观察者可能会消耗较多的时间和资源。特别是在一些对性能要求较高的场景下可能需要对通知机制进行优化比如采用异步通知等方式。存在循环依赖风险如果观察者在更新自己状态的过程中又对主题进行了操作可能会导致循环依赖使得系统的逻辑变得复杂甚至出现死循环等问题。在设计和实现过程中需要特别注意避免这种情况。