.NET高级面试指南专题十四【 观察者模式介绍,最常用的设计模式之一】

在这里插入图片描述

简介:

观察者模式(Observer Pattern)是一种行为型设计模式,其目的是定义了一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并自动更新。

原理:

在观察者模式中,有两种角色:观察者(Observer)和被观察者(Subject)。被观察者维护一个观察者列表,并提供注册和删除观察者的方法。当被观察者的状态发生变化时,它会通知所有注册的观察者,调用它们的更新方法,从而使得观察者可以根据被观察者的状态进行相应的操作。

优点:

  • 松耦合(Loose Coupling):被观察者和观察者之间是松耦合的,它们之间只有一个抽象的依赖关系,不会互相影响。
  • 可扩展性(Scalability):可以动态地添加和删除观察者,而不需要修改被观察者的代码,使得系统更易于扩展和维护。
  • 可重用性(Reusability):观察者模式提供了一种通用的机制,使得被观察者和观察者可以独立变化,可以在不同的场景中被重复使用。

缺点:

  • 过多的通知(Overhead):如果被观察者对象有很多状态需要通知观察者,那么可能会产生大量的通知,导致性能问题。
  • 可能引起循环引用(Circular References):如果观察者和被观察者相互引用,可能会导致内存泄漏或其他问题。
  • 通知的顺序不确定(Ordering Issues):观察者收到通知的顺序可能是不确定的,这可能会导致一些问题,特别是在多线程环境下。

常用场景:
观察者模式常用于以下情况:

  1. 当一个对象的改变需要同时改变其他对象,并且不知道具体有多少对象需要改变时。
  2. 当一个对象的改变需要通知其他对象,但又不希望这些对象是紧密耦合的。

在C#中,观察者模式是一种常见的设计模式,可以在许多地方使用。

  1. 事件处理:C#中的事件(Event)机制本质上就是观察者模式的一种实现。事件的订阅者(Subscriber)注册到事件上,当事件发生时,所有订阅者都会收到通知并执行相应的操作。

  2. GUI编程:在Windows Forms、WPF等GUI编程框架中,观察者模式被广泛应用。例如,当用户与界面进行交互时,界面上的控件(如按钮、文本框等)可以作为被观察者,而事件处理程序则充当观察者,当用户进行操作时,控件会通知事件处理程序执行相应的操作。

  3. 消息通知:在消息队列(Message Queue)或事件总线(Event Bus)等场景中,观察者模式常被用于实现消息的订阅和分发。当消息发布时,所有订阅该消息的对象都会收到通知并执行相应的处理逻辑。

  4. 数据绑定:在C#中,通过数据绑定机制,可以将界面上的控件与数据模型进行绑定,当数据模型发生变化时,界面上的控件会自动更新。这种数据绑定机制本质上也是观察者模式的一种应用。WPF的MVVM原理也是基于此

  5. 多线程编程:在多线程编程中,经常会使用观察者模式来实现异步通知机制。例如,当一个线程完成某项任务时,可以通过观察者模式通知其他线程执行相应的操作。

简单的C#代码示例

using System;

// 定义事件发布者
public class EventPublisher
{
    // 定义事件
    public event EventHandler<string> MyEvent;

    // 触发事件的方法
    public void RaiseEvent(string message)
    {
        MyEvent?.Invoke(this, message);
    }
}

// 定义事件订阅者
public class EventSubscriber
{
    private readonly string _name;

    public EventSubscriber(string name)
    {
        _name = name;
    }

    // 事件处理方法
    public void HandleEvent(object sender, string message)
    {
        Console.WriteLine($"{_name} received message: {message}");
    }
}

class Program
{
    static void Main(string[] args)
    {
        // 创建事件发布者
        var publisher = new EventPublisher();

        // 创建事件订阅者
        var subscriber1 = new EventSubscriber("Subscriber 1");
        var subscriber2 = new EventSubscriber("Subscriber 2");

        // 订阅事件
        publisher.MyEvent += subscriber1.HandleEvent;
        publisher.MyEvent += subscriber2.HandleEvent;

        // 触发事件
        publisher.RaiseEvent("Hello, world!");

        // 移除订阅者
        publisher.MyEvent -= subscriber2.HandleEvent;

        // 再次触发事件
        publisher.RaiseEvent("Goodbye!");

        Console.ReadLine();
    }
}

其他地方用到的 观察者模式
在前端开发中,Vue.js框架本身就是基于观察者模式设计的,它提供了一种响应式的数据绑定机制,使得视图与数据之间能够保持同步。下面是在Vue.js中使用观察者模式的简单示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue Observer Example</title>
    <!-- 引入Vue.js -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <p>{{ message }}</p>
        <button @click="updateMessage">Update Message</button>
    </div>

    <script>
        // 创建一个Vue实例
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello, Vue!'
            },
            methods: {
                // 更新数据的方法
                updateMessage: function() {
                    this.message = 'Hello, Vue.js!';
                }
            }
        });
    </script>
</body>
</html>

在这个示例中,我们创建了一个Vue实例,并在data选项中定义了一个名为message的数据属性。在HTML模板中,我们通过插值表达式{{ message }}将message数据属性绑定到页面上,当message的值发生变化时,页面上的内容也会相应地更新。通过点击按钮,调用updateMessage方法来更新message的值,这时Vue会自动通知相关的视图进行更新。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/429111.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

002-CSS-三角形

三角形 普通三角形带阴影的三角形&#xff1a;box-shadow带阴影的三角形&#xff1a;filter 普通三角形 &#x1f4a1; Tips&#xff1a;设置 div 盒子宽高为零&#xff0c;使用单边框实现 .triangle {width: 0;height: 0;border: 20px solid transparent;border-top-color: …

把python完全卸载干净

1.winR&#xff0c;输入control回车&#xff0c;点击程序和功能&#xff0c;在搜索框输入python&#xff0c;右键点击卸载 2、找到Python安装路径&#xff0c;把所有文件全部删除。 安装路径可以打开CMD输入&#xff1a;where python 3、强制删除Python.exe 打开cmd&#xff…

使用Java生成JWT(JSON Web Token)的详细指南

介绍 在现代应用程序中&#xff0c;身份验证和授权是至关重要的。JSON Web Token&#xff08;JWT&#xff09;是一种开放标准&#xff08;RFC 7519&#xff09;&#xff0c;它定义了一种紧凑且自包含的方式用于在各方之间安全地传输信息。在本文中&#xff0c;我们将学习如何使…

大厂报价查询系统性能优化之道!

0 前言 机票查询系统&#xff0c;日均亿级流量&#xff0c;要求高吞吐&#xff0c;低延迟架构设计。提升缓存的效率以及实时计算模块长尾延迟&#xff0c;成为制约机票查询系统性能关键。本文介绍机票查询系统在缓存和实时计算两个领域的架构提升。 1 机票搜索服务概述 1.1 …

在k8s上部署dolphinscheduler

&#xff08;作者&#xff1a;陈玓玏&#xff09; 一、 前提条件 已部署k8s&#xff0c;版本信息如下&#xff1a; k8s为单机部署&#xff1b;已部署nfs&#xff0c;版本如下&#xff1b; 二、 部署helm 以下步骤安装的是二进制版本&#xff0c;如果通过脚本安装&#…

Bert Encoder和Transformer Encoder有什么不同

前言&#xff1a;本篇文章主要从代码实现角度研究 Bert Encoder和Transformer Encoder 有什么不同&#xff1f;应该可以帮助你&#xff1a; 深入了解Bert Encoder 的结构实现深入了解Transformer Encoder的结构实现 本篇文章不涉及对注意力机制实现的代码研究。 注&#xff1a;…

在Linux以命令行方式(静默方式/非图形化方式)安装MATLAB(正版)

1.根据教程&#xff0c;下载windows版本matlab&#xff0c;打开图形化界面&#xff0c;选择linux版本的只下载不安装 2.获取安装文件夹 3.获取许可证 4.安装 &#xff08;1&#xff09;跳过引用文章的2.2章节 &#xff08;2&#xff09;本文的安装文件夹代替引用文章的解压IS…

CSS变量和@property

CSS变量 var() CSS 变量是由CSS作者定义的实体&#xff0c;其中包含要在整个文档中重复使用的特定值。使用自定义属性来设置变量名&#xff0c;并使用特定的 var() 来访问。&#xff08;比如 color: var(--main-color);&#xff09;。 基本用法 CSS变量定义的作用域只在定义该…

Rio: Order-Preserving and CPU-Efficient Remote Storage Access——论文泛读

EuroSys 2023 Paper 论文阅读笔记整理 问题 现代NVMe SSD和RDMA网络提供了更高的带宽和并发性&#xff0c;但现有的网络存储系统&#xff08;例如&#xff0c;基于结构的NVMe&#xff09;&#xff0c;由于存储订购保证效率低下&#xff0c;无法充分利用这些新设备。在这些系统…

[DevOps云实践] 3大云厂商(AWS/GoogleCP/Azure)的服务对比一览

[DevOps云实践] 3大云厂商(AWS/GoogleCP/Azure)的服务对比一览 如今有很多人在使用云端或者把他们的基础架构迁移到云端。每个云服务提供商都有其优势和劣势,大部分情况下您的选择将基于您想要在云中构建什么。您公司的各个团队也很可能会倾向于为他们的特定项目使用不同的…

【论文解读】Robust Collaborative 3D Object Detection in Presence of Pose Errors

CoAlign 摘要引言方法实验结论 摘要 协同3D对象检测利用多个代理之间的信息交换&#xff0c;以在存在诸如遮挡之类的传感器损伤的情况下提高对象检测的准确性。然而&#xff0c;在实践中&#xff0c;由于定位不完善而导致的姿态估计误差会导致空间消息错位&#xff0c;并显著降…

使用html网页播放多个视频的几种方法

前言 因为项目测试需要&#xff0c;我需要可以快速知道自己推流的多路视频流质量&#xff0c;于是我想到可以使用html网页来播放视频&#xff0c;实现效果极其简单&#xff0c;方法有好几种&#xff0c;以下是几种记录&#xff1a; 注意&#xff1a;测试过&#xff0c;VLC需要使…

微服务:Feign篇

1.什么是Feign Feign是一种声明式、模板化的HTTP客户端&#xff0c;可用于调用HTTP API实现微服务之间的远程服务调用。它的特点是使用少量的配置定义服务客户端接口&#xff0c;可以实现简单和可重用的RPC调用。 先来看我们以前利用RestTemplate发起远程调用的代码&#xff…

卡密交易系统 卡密社区SUP系统源码 分销系统平台 分销商城系统开发

卡密社区SUP系统总控源码主站分销系统功能源码 跟以前的卡盟那种控制端差不多总控可以给别人开通&#xff0c;分销&#xff0c;主站&#xff0c;类似自己做系统商一样&#xff0c;自助发卡&#xff0c;卡密交易系统。 搭建环境Nginx1.22 mysql 5.7 php8.1 rids 7.2 安装方法…

【C++】十大排序算法之 插入排序 希尔排序

本次介绍内容参考自&#xff1a;十大经典排序算法&#xff08;C实现&#xff09; - fengMisaka - 博客园 (cnblogs.com) 排序算法是《数据结构与算法》中最基本的算法之一。 十种常见排序算法可以分为两大类&#xff1a; 比较类排序&#xff1a;通过比较来决定元素间的相对次序…

鸿蒙开发就业前景以及发展方向分析~

鸿蒙操作系统作为华为公司自主研发的操作系统&#xff0c;已经成为当下炙手可热的话题。作为一个全新的操作系统&#xff0c;鸿蒙开发为IT行业带来了巨大的就业机会。本文将围绕鸿蒙开发的就业前景以及发展方向展开讨论。 一、鸿蒙开发就业前景 随着鸿蒙操作系统的发布&#…

二叉树——从中序与后序遍历序列构造二叉树、654. 最大二叉树、617. 合并二叉树

从中序与后序遍历序列构造二叉树 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 在这里插入代码片 输入&#xff1a;inorder [9,3,15…

leetcode 热题 100_和为 K 的子数组

题解一&#xff1a; 前缀和数组哈希表&#xff1a;可以计算所有子数组之和暴力求解&#xff0c;但复杂度太高。对于子数组求和的过程&#xff0c;我们可以采用前缀和数组进行优化&#xff0c;前缀和数组中pre[index]代表nums[0]~nusm[index]之和&#xff0c;当我们要计算子数组…

NLP评价指标

一、分类任务常见评估&#xff1a; 准确度(Accuracy) 评估预测正确的比例&#xff0c;精确率(Precision) 评估预测正例的查准率&#xff0c;召回率(Recall) 评估真实正例的查全率。如果是多分类&#xff0c;则每个类别各自求P、R最终求平均值。 TP&#xff08;True Positives…

SwiftUI 在 App 中弹出全局消息横幅(上)

功能需求 在 SwiftUI 开发的 App 界面中,有时我们需要在全局层面向用户展示一些消息: 如上图所示:我们弹出的全局消息横幅位于所有视图之上,这意味这它不会被任何东西所遮挡;而且用户可以点击该横幅关闭它。这是怎么做到的呢? 在本篇博文中,您将学到以下内容 功能需求…
最新文章