Java笔试面试题AI答之设计模式(4)

文章目录

  • 16. 简述什么是观察者模式?
      • 基本概念
      • 主要特点
      • 实现方式
      • 应用场景
      • 优缺点
  • 17. 请列举观察者模式应用场景 ?
  • 18. 请用Java代码实现观察者模式的案例 ?
  • 19. 什么是装饰模式?
      • 定义与特点
      • 结构与角色
      • 工作原理
      • 优点
      • 应用场景
      • 示例
  • 20. 请用Java代码实现装饰者模式的案例 ?

16. 简述什么是观察者模式?

观察者模式(Observer Pattern),也被称为模型-视图(Model-View)模式、源-收听者(Listener)模式或从属者模式,是软件设计模式中的一种行为型模式。该模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖于它的对象都会得到通知并被自动更新。以下是观察者模式的详细解释:

基本概念

  • 观察者(Observer):等待被通知的对象,它持有对一个或多个主题(Subject)的引用,以便在主题状态发生变化时得到更新。
  • 主题(Subject):也被称为被观察者,当它的状态发生变化时,会主动通知所有注册的观察者对象,使得它们能够自动更新自己。

主要特点

  1. 松耦合:主题和观察者之间通过抽象接口进行交互,使得它们可以独立演化而不影响彼此。
  2. 一对多关系:一个主题可以有多个观察者,并且它们之间没有直接联系。
  3. 可扩展性:可以随时增加新的观察者或删除现有观察者,无需修改主题或观察者的代码。
  4. 实时性:实现了实时更新机制,当主题状态改变时能够即刻通知相关观察者。

实现方式

观察者模式通常包含以下几个角色:

  • 抽象主题(Subject):定义了一个用于保存观察者对象的集合以及一个用于增加、删除和通知观察者的接口。
  • 具体主题(Concrete Subject):实现了抽象主题定义的接口,用于管理具体的观察者对象集合,并在需要时向观察者发送通知。
  • 抽象观察者(Observer):定义了一个更新接口,该接口用于响应主题状态的变化。
  • 具体观察者(Concrete Observer):实现了抽象观察者接口,并在接收到主题的通知时执行相应的操作。

应用场景

观察者模式在许多应用中都有广泛的应用,特别是当存在对象之间的一对多关系,并且需要实时通知和更新时。以下是一些典型的应用场景:

  • 消息发布/订阅系统:观察者模式可以用于构建消息发布/订阅系统,其中消息发布者充当主题(被观察者),而订阅者则充当观察者。
  • 图形用户界面(GUI):在图形用户界面中,用户界面的各个部分(如按钮、文本框等)可以作为观察者,而它们所依赖的数据或状态则可以作为主题。当数据或状态发生变化时,界面元素会自动更新以反映这些变化。
  • 业务对象之间的交互:在业务系统中,不同业务对象之间可能存在复杂的依赖关系。通过使用观察者模式,可以将这些依赖关系解耦,使得当某个业务对象的状态发生变化时,能够自动通知并更新依赖它的其他业务对象。

优缺点

  • 优点
    • 降低了对象之间的耦合度,提高了系统的灵活性和可扩展性。
    • 实现了对象之间的动态关联,可以在运行时动态地添加或删除观察者。
    • 简化了对象之间的通信机制,使得系统更加易于理解和维护。
  • 缺点
    • 如果一个主题通知了太多的观察者,可能会导致系统性能下降。
    • 如果观察者和主题之间存在循环依赖关系,可能会导致系统崩溃。
    • 在某些情况下,观察者可能无法感知到其他已注册的新类型或特定类型的观察者。

总的来说,观察者模式是一种非常有用的设计模式,它能够帮助我们解决对象之间的一对多依赖关系问题,并提高系统的灵活性和可扩展性。然而,在使用时也需要注意其潜在的缺点和限制。

17. 请列举观察者模式应用场景 ?

观察者模式(Observer Pattern)是一种设计模式,主要用于当一个对象的状态发生变化时,能够自动通知多个依赖于它的对象并使它们同步更新。它是一种行为型模式,常用于实现发布-订阅机制。以下是观察者模式的一些主要应用场景:

  1. 图形用户界面(GUI)事件监听

    • 在图形用户界面编程中,按钮、文本框等控件的事件处理通常使用观察者模式。控件(如按钮)作为被观察者,当用户进行某些操作时(如点击按钮),会通知观察者(即事件处理器或监听器)来处理相应的事件。例如,当用户点击按钮时,按钮对象会通知所有注册的监听器,然后调用这些监听器的处理方法来响应点击事件。
  2. 数据模型与视图同步

    • 在模型-视图-控制器(MVC)架构中,观察者模式常用于数据模型和视图之间的更新同步。当模型中的数据发生变化时,所有依赖该模型的视图都会自动更新显示。例如,在图形化的应用程序中,如果数据模型发生改变,表格视图和图表视图等都会同步更新以反映最新数据。
  3. 发布-订阅系统

    • 观察者模式是发布-订阅系统的基础。在这种系统中,发布者(被观察者)发布消息,订阅者(观察者)订阅感兴趣的消息类型。当某个消息类型被发布时,订阅者会收到通知并执行相应的处理逻辑。这种模式常见于消息中间件系统,如Kafka或RabbitMQ,它们允许不同的服务订阅某个主题,当该主题发布消息时,所有订阅者都会接收消息并处理。
  4. 股票价格监控

    • 在金融系统中,股票价格可能频繁变动,多个不同的系统(如显示价格的终端、交易系统等)都依赖这些变化。观察者模式可以让股票价格的变化自动通知所有依赖该数据的系统。当股票价格更新时,所有注册的投资者或系统会收到通知,并相应调整其交易策略或显示界面。
  5. 缓存系统的失效通知

    • 在一些分布式系统中,当某个缓存中的数据失效时,观察者模式可以用于通知相关系统或服务进行缓存更新或重新加载数据。例如,当数据库中的数据被更新时,缓存层会收到通知,标记缓存数据失效,以确保下一次请求能获取到最新的数据。
  6. 社交媒体的通知机制

    • 在社交媒体平台中,当用户发布新动态时,所有关注者都应及时收到通知。这里的用户是被观察者,关注者是观察者。用户发布新内容时,平台会通知所有关注者。例如,在微博、推特等平台中,当某个用户发布新动态时,所有关注者都会在时间线上看到该动态。
  7. 日志系统

    • 在某些复杂的系统中,日志的记录可能需要发送到多个地方,如文件、数据库、监控系统等。观察者模式可以用于实现这样的需求,其中日志记录器充当被观察者,而观察者可以是日志分析器、报警系统等。当日志发生变化时,观察者将收到通知并执行相应的操作,如生成报告、发送警报等。
  8. 定时任务或调度器

    • 一些定时任务系统需要在指定的时间通知多个任务执行。观察者模式可以很好地支持这一功能。调度器作为被观察者,任务作为观察者,调度器到达指定时间后通知所有观察者执行任务。例如,定时任务调度器可以通知多个系统组件执行某些例行维护任务。
  9. 游戏中的状态变化通知

    • 在游戏开发中,某些对象的状态变化可能影响多个其他对象。例如,当游戏角色的生命值发生变化时,UI界面需要更新生命值显示,敌对角色可能需要调整攻击策略,音效系统可能需要播放不同的音效。观察者模式可以确保这些变化能够自动通知并同步更新到所有相关的对象。

综上所述,观察者模式在需要通知多个对象进行同步更新的场合具有广泛的应用价值,它能够提高系统的扩展性和可维护性。

18. 请用Java代码实现观察者模式的案例 ?

观察者模式(Observer Pattern)是一种行为设计模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

以下是一个使用Java实现的简单观察者模式案例:

首先,定义一个主题接口(Subject),它包含一个注册观察者、删除观察者以及通知观察者的方法:

import java.util.ArrayList;
import java.util.List;public interface Subject {// 注册观察者void registerObserver(Observer o);// 删除观察者void removeObserver(Observer o);// 通知所有观察者void notifyObservers();
}

然后,定义一个观察者接口(Observer),它包含一个更新方法,用于在接收到通知时执行:

public interface Observer {// 接收通知时调用的更新方法void update(String message);
}

接下来,实现具体的主题类(ConcreteSubject),它实现了Subject接口,并维护了一个观察者列表:

public class ConcreteSubject implements Subject {private List<Observer> observers;private String subjectState;public ConcreteSubject() {this.observers = new ArrayList<>();}@Overridepublic void registerObserver(Observer o) {if (!observers.contains(o)) {observers.add(o);}}@Overridepublic void removeObserver(Observer o) {observers.remove(o);}@Overridepublic void notifyObservers() {for (Observer observer : observers) {observer.update(subjectState);}}// 用于设置主题状态并通知所有观察者public void setState(String state) {this.subjectState = state;notifyObservers();}// Getter和Setter(如果需要)public String getState() {return subjectState;}
}

最后,实现具体的观察者类(ConcreteObserver),它实现了Observer接口:

public class ConcreteObserver implements Observer {private String name;private String observerState;public ConcreteObserver(String name) {this.name = name;}@Overridepublic void update(String message) {observerState = message;readObserverState();}private void readObserverState() {System.out.println(name + " received state: " + observerState);}
}

现在,我们可以使用这些类来演示观察者模式:

public class ObserverPatternDemo {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();Observer observer1 = new ConcreteObserver("Observer 1");Observer observer2 = new ConcreteObserver("Observer 2");subject.registerObserver(observer1);subject.registerObserver(observer2);subject.setState("Hello World!");// 如果需要,可以删除某个观察者// subject.removeObserver(observer1);// subject.setState("Another message");}
}

在这个例子中,ConcreteSubject 类维护了一个观察者列表,并在其状态改变时通过调用 notifyObservers() 方法来通知所有已注册的观察者。每个 ConcreteObserver 对象在接收到通知时都会更新自己的状态,并通过 readObserverState() 方法输出接收到的消息。

19. 什么是装饰模式?

装饰模式是一种常见的设计模式,主要用于在不改变原有类结构的情况下,动态地给对象增加新的功能或职责。这种模式通过创建一个包装对象(即装饰器)来包裹真实的对象,从而达到扩展对象功能的目的。以下是装饰模式的详细简述:

定义与特点

  • 定义:装饰模式(Decorator Pattern)动态地给一个对象增加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。
  • 特点
    • 多用组合,少用继承:通过对象间的组合关系来实现功能的扩展,而不是通过继承关系。
    • 开闭原则:对扩展开放,对修改关闭。可以在不修改原有类代码的情况下,通过增加新的装饰器类来扩展功能。
    • 透明性:装饰对象与真实对象有相同的接口,这样客户端就可以以相同的方式与它们交互,无需知道它们是真实对象还是装饰对象。

结构与角色

装饰模式包含以下几个角色:

  1. 抽象构件(Component)角色:定义一个对象的接口,可以给这些对象动态地添加一些职责。
  2. 具体构件(Concrete Component)角色:定义了一个具体的对象,也可以给这个对象添加一些职责。
  3. 装饰(Decorator)角色:持有一个构件(Component)对象的引用,并定义一个与抽象构件接口一致的接口。
  4. 具体装饰(Concrete Decorator)角色:负责给构件对象“贴上”一些新的职责。

工作原理

  • 装饰模式通过创建一个包装对象(即装饰器)来包裹真实对象。
  • 装饰器对象与真实对象有相同的接口,客户端可以通过这个接口与它们进行交互。
  • 装饰器对象可以在转发请求给真实对象之前或之后增加一些新的功能或行为。

优点

  • 灵活性:可以在不修改原有类代码的情况下,通过增加新的装饰器类来扩展功能。
  • 扩展性:遵循开闭原则,对扩展开放,对修改关闭。
  • 减少子类数量:通过组合关系替代继承关系,减少了子类的数量,降低了系统的复杂度。

应用场景

  • 当需要给某个对象动态地增加一些职责时。
  • 当不能使用继承的方式来扩展对象的功能时(例如,类已经被定义为final,或者出于设计上的考虑不希望产生大量的子类)。
  • 当一个类的功能比较复杂,而且需要经常扩展时,可以使用装饰模式来简化类的设计。

示例

假设有一个简单的图形界面程序,其中有一个按钮(Button)类。现在需要给这个按钮增加一些新的样式或功能,比如边框、颜色等。使用装饰模式,可以创建一个或多个装饰器类(如BorderDecorator、ColorDecorator等),每个装饰器类都负责给按钮增加一种特定的样式或功能。这样,就可以通过组合不同的装饰器来创建具有多种样式和功能的按钮对象,而无需修改原始的按钮类代码。

20. 请用Java代码实现装饰者模式的案例 ?

装饰者模式(Decorator Pattern)是一种用于动态地给一个对象添加一些额外的职责,就增加功能来说,装饰者模式相比生成子类更为灵活。这种模式创建了一个装饰者类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

下面是一个使用Java实现的装饰者模式案例,假设我们有一个咖啡类(Coffee),我们可以使用不同的调料(如奶精、摩卡等)来装饰它,增加它的口味。

首先,定义一个咖啡接口(Coffee)和一个具体的咖啡类(如Espresso)实现这个接口:

interface Coffee {double cost();String getDescription();
}class Espresso implements Coffee {@Overridepublic double cost() {return 1.99;}@Overridepublic String getDescription() {return "Espresso";}
}

接下来,定义一个装饰者抽象类,它实现了Coffee接口,并持有一个Coffee对象的引用,用于调用实际咖啡的方法:

abstract class CoffeeDecorator implements Coffee {protected Coffee decoratedCoffee;public CoffeeDecorator(Coffee decoratedCoffee) {this.decoratedCoffee = decoratedCoffee;}@Overridepublic double cost() {return decoratedCoffee.cost();}@Overridepublic String getDescription() {return decoratedCoffee.getDescription();}
}

现在,我们可以创建具体的装饰者类,比如MochaMilk,它们扩展了CoffeeDecorator类,并添加了额外的功能(如增加成本、修改描述):

class Mocha extends CoffeeDecorator {public Mocha(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic double cost() {return 0.20 + super.cost(); // 假设加摩卡需要额外0.20}@Overridepublic String getDescription() {return super.getDescription() + ", Mocha";}
}class Milk extends CoffeeDecorator {public Milk(Coffee decoratedCoffee) {super(decoratedCoffee);}@Overridepublic double cost() {return 0.10 + super.cost(); // 假设加奶需要额外0.10}@Overridepublic String getDescription() {return super.getDescription() + ", Milk";}
}

最后,我们可以使用这些类来创建一个具有多种口味的咖啡,并查看其成本和描述:

public class DecoratorPatternDemo {public static void main(String[] args) {Coffee espresso = new Espresso();System.out.println(espresso.getDescription() + " $" + espresso.cost());Coffee espressoMocha = new Mocha(espresso);System.out.println(espressoMocha.getDescription() + " $" + espressoMocha.cost());Coffee espressoMochaMilk = new Milk(espressoMocha);System.out.println(espressoMochaMilk.getDescription() + " $" + espressoMochaMilk.cost());}
}

输出将会是:

Espresso $1.99
Espresso, Mocha $2.19
Espresso, Mocha, Milk $2.29

这样,我们就通过装饰者模式在运行时动态地给咖啡添加了不同的调料,而无需修改咖啡类或创建新的咖啡子类。

答案来自文心一言,仅供参考
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基于大数据的电子产品需求数据分析系统的设计与实现(Python Vue Flask Mysql)

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

【GlobalMapper精品教程】088:按点线面空间位置选择案例

按点线面空间位置选择的原则为:点线面的排列组合。 文章目录 一、选择线要素附近的点二、选择相交或触碰所选线的区和线三、选择包含点的区要素四、选择选定区域内的点要素一、选择线要素附近的点 启动该工具之前,首先要选择线,例如,选择某一段铁路5km范围之内的县城驻地。…

DeepSeek 2.5本地部署的实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。授权多项发明专利。对机器学…

[Meachines] [Medium] Sniper RFI包含远程SMB+ powershell用户横向+CHM武器化权限提升

信息收集 IP AddressOpening Ports10.10.10.151TCP:80,135,139,445,49667 $ nmap -p- 10.10.10.151 --min-rate 1000 -sC -sV -Pn PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 10.0 |_http-server-header: Microsoft-IIS/10.…

三阶魔方还原法 勾上回下 上右左左右

三阶魔方还原法&#xff1a; 1小白花 &#xff08;转3换1&#xff09; 2白十字架 (侧与中心同色 下下) 3第一层 &#xff08;找位置角块放顶点 勾上回下&#xff09; 4 第二层 &#xff08;颜色边 勾上回下 再单白边 勾上回下&#xff09; 5 黄十字架 &#xff08;无黄边 压 勾…

0.设计模式总览——设计模式入门系列

在现代软件开发中&#xff0c;设计模式为我们提供了优秀的解决方案&#xff0c;帮助我们更好地组织代码和架构。本系列专栏将对设计模式的基本思想、原则&#xff0c;以及常用的分类、实现方式&#xff0c;案例对比、以及使用建议&#xff0c;旨在提高开发者对设计模式的理解和…

【算法】BFS系列之 拓扑排序

【ps】本篇有 3 道 leetcode OJ。 目录 一、算法简介 二、相关例题 1&#xff09;课程表 .1- 题目解析 .2- 代码编写 2&#xff09;课程表 II .1- 题目解析 .2- 代码编写 3&#xff09;火星词典 .1- 题目解析 .2- 代码编写 一、算法简介 【补】图的基本概念 &#…

HTML翻牌器:用CSS和HTML元素创造动态数字展示

HTML翻牌器&#xff1a;用CSS和HTML元素创造动态数字展示 前言 翻牌器是一种数字动态展示形式&#xff0c;在生活中常见的例如翻牌计分、翻牌时钟等。 之所以以翻牌的形式是因为其物理设计的原因使其只能滚动翻牌展示数字&#xff0c;在电子显示设备不普及时&#xff0c;使用…

Leetcode - 139双周赛

目录 一&#xff0c;3285. 找到稳定山的下标 二&#xff0c;3286. 穿越网格图的安全路径 三&#xff0c;3287. 求出数组中最大序列值 四&#xff0c;3288. 最长上升路径的长度 一&#xff0c;3285. 找到稳定山的下标 本题就是找[0&#xff0c; n-2]中&#xff0c;height[i]…

C++入门12——详解多态2

上篇文章&#xff08;C入门12——详解多态1&#xff09;中&#xff0c;我们介绍了C多态的概念和用法&#xff0c;但是只知其然而不知其所以然是万万不行的&#xff0c;所以本篇文章将从探案的角度详细介绍多态的原理。 1. 虚函数表 想要弄懂多态的原理&#xff0c;首先要了解一…

数据结构与算法学习day22-回溯算法-分割回文串、复原IP地址、子集

一、分割回文串 1.题目 131. 分割回文串 - 力扣&#xff08;LeetCode&#xff09; 2.思路 分割回文串可以抽象为一棵树形结构。 递归用来纵向遍历&#xff0c;for循环用来横向遍历&#xff0c;切割线&#xff08;就是图中的红线&#xff09;切割到字符串的结尾位置&#xf…

STM32F407单片机编程入门(十三) 单片机IAP(在应用编程)详解及实战源码

文章目录 一.概要二.STM32F407VET6单片机IAP介绍1.STM32F407VET6单片机IAP基本原理2.STM32F407VET6单片机IAP基本流程 三.配置一个BOOT工程四.配置一个APP工程五.工程源代码下载六.小结 一.概要 STM32单片机程序升级方法有很多种&#xff0c;主要有以下几种&#xff1a; 1.将…

【LeetCode】146. LRU缓存

1.题目 2.思想 3.代码 3.1 代码1 下面这是一版错误的代码。错误的原因在于逻辑不正确导致最后的代码也是不正确的。 class LRUCache:def __init__(self, capacity: int):self.time 0 # 用于全局记录访问的时间self.num2time {} # 数字到时间的映射self.key2val {} # 数字…

如何理解MVCC

MVCC是什么&#xff1f; MVCC&#xff0c;是MultiVersion Concurrency Control的缩写&#xff0c;翻译成中文就是多版本并发控制&#xff0c;多个事务同时访问同一数据时&#xff0c;调控每一个事务获取到数据的具体版本。和数据库锁一样&#xff0c;它也是一种并发控制的解决…

实时同步 解决存储问题 sersync

目录 1.sersync服务 2.sersync同步整体架构 ​编辑 3.rsync服务准备 4.sersync部署使用 5.修改配置文件 6.启动sersync 7.接入nfs服务 8.联调测试 1.sersync服务 sersync服务其实就是由两个服务组成一个是inotify服务和rsync服务组成 inotify服务用来监控那个…

Infineon——TC397 Multicore简介

文章目录 前言一、TC397简介二、命名规则三、多核开发建议 前言 AURIX™ TC3xx微控制器架构具有多达6个独立的处理器内核CPU0…CPU5, 可在一个统一平台上无缝托管多个应用程序和操作系统. 由于实现了具有独立读取接口的多个程序Flash模块, 该架构支持进一步的实时处理. AURIX™…

自学笔记之TVM编译器框架 ,核心特性,模型优化概述,AI应用落地

最近在学习一些和芯片 AI相关的知识&#xff0c;重点了解了一下TVM&#xff0c;我自己认为TVM在AI应用落地类似的项目中&#xff0c;用途还是非常广泛的&#xff0c;现在把一些重要的笔记贴在下面&#xff0c;有两篇原帖链接也附上&#xff0c;感兴趣的同学可以学习一下。 TVM…

小球轻重的测量

设有12个小球。其中11个小球的重量相同&#xff0c;称为好球&#xff1b;有一个小球的重量与11个好球的重量不同&#xff08;或轻或重&#xff09;&#xff0c;称这个小球为坏球。试编写一个算法&#xff0c;用一个无砝码的天平称三次找出这个坏球&#xff0c;并确定其比好球轻…

SpringCloud入门(五)Nacos注册中心(上)

国内公司一般都推崇阿里巴巴的技术&#xff0c;比如注册中心&#xff0c;SpringCloudAlibaba也推出了一个名为Nacos的注册中心。Dynami Naming and Configuration Service。是阿里巴巴2018年7月开源的项目。 Nacos是阿里巴巴的产品&#xff0c;现在是SpringCloud中的一个组件。…

智谱清影 - CogVideoX-2b-部署与使用

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 体验地址&#xff1a;[丹摩DAMODEL官网](https://www.damodel.com/console/overview) CogVideoX 简介本篇将详细介绍使用丹摩服务器部…