持续总结中!2024年面试必问 20 道设计模式面试题(四)

2024-06-19 00:28

本文主要是介绍持续总结中!2024年面试必问 20 道设计模式面试题(四),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

上一篇地址:持续总结中!2024年面试必问 20 道设计模式面试题(三)-CSDN博客

七、观察者模式(Observer Pattern)是如何工作的?

观察者模式(Observer Pattern),又称为发布-订阅模式,是一种行为设计模式,它定义了对象间的一种一对多的依赖关系,使得当一个对象状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式通常用于实现分布式事件处理系统。

观察者模式的主要组件:

  1. 主题(Subject)

    • 主题是观察者模式的核心,它维护了一组观察者对象的引用,并提供接口用于注册(attach)、移除(detach)和通知(notify)观察者。
  2. 观察者(Observer)

    • 观察者是一个接口,定义了观察者对象必须实现的更新接口,以便在主题状态改变时得到通知。
  3. 具体主题(ConcreteSubject)

    • 具体主题实现了主题接口,存储状态信息,并提供方法供观察者注册和移除自己。当状态发生改变时,它会自动通知所有注册的观察者。
  4. 具体观察者(ConcreteObserver)

    • 具体观察者实现了观察者接口,根据主题的当前状态更新自己的状态。通常包含一个指向具体主题的引用,但这个引用不是必需的,取决于具体的实现。
  5. 客户端(Client)

    • 客户端代码创建并配置了具体主题和具体观察者,将观察者注册到主题上,并触发事件以演示观察者模式的工作。

观察者模式的工作原理:

  1. 注册观察者:具体观察者对象通过调用具体主题的注册方法将自己注册为观察者。

  2. 状态变更:当具体主题的状态发生变化时,它会调用所有注册观察者的更新方法。

  3. 通知观察者:具体主题通过调用观察者的更新方法来通知它们状态已经改变,通常传递一些必要的信息,如变化的状态本身或一个事件对象。

  4. 更新状态:具体观察者接收到通知后,根据传递的信息更新自己的状态。

示例代码(Java):

// 观察者接口
interface Observer {void update(String message);
}// 主题接口
interface Subject {void registerObserver(Observer o);void removeObserver(Observer o);void notifyObservers();
}// 具体主题
class ConcreteSubject implements Subject {private List<Observer> observers = new ArrayList<>();private String state;public void registerObserver(Observer o) {observers.add(o);}public void removeObserver(Observer o) {observers.remove(o);}public void notifyObservers() {for (Observer observer : observers) {observer.update(state);}}public void setState(String state) {this.state = state;notifyObservers();}
}// 具体观察者
class ConcreteObserver implements Observer {private ConcreteSubject subject;public ConcreteObserver(ConcreteSubject subject) {this.subject = subject;subject.registerObserver(this);}@Overridepublic void update(String message) {System.out.println("Received update: " + message);}
}// 客户端代码
public class ObserverPatternDemo {public static void main(String[] args) {ConcreteSubject subject = new ConcreteSubject();new ConcreteObserver(subject); // 注册观察者subject.setState("State 1"); // 状态变更,通知观察者subject.setState("State 2"); // 再次状态变更}
}

在这个示例中,ConcreteSubject是具体主题,它维护了一个观察者列表,并在状态变化时通知所有观察者。ConcreteObserver是具体观察者,实现了Observer接口,并在接收到更新时打印消息。客户端代码创建了主题和观察者,并演示了状态更新和观察者注册的过程。

观察者模式使得对象间的耦合度降低,当一个对象的状态变化时,依赖于它的对象会自动更新,而无需直接调用这些对象的方法。这使得系统更加灵活和易于维护。

八、装饰器模式(Decorator Pattern)和适配器模式有何不同?

装饰器模式(Decorator Pattern)和适配器模式(Adapter Pattern)虽然都是结构型设计模式,但它们解决的问题和设计目的是不同的。以下是两种模式的主要区别:

目的不同:

  • 适配器模式 主要用于使不兼容的接口能够一起工作。它通常用于将一个类的接口转换成客户端期望的另一个接口,从而让原本由于接口不兼容而不能一起工作的类可以协同工作。

  • 装饰器模式 主要用于动态地给一个对象添加额外的职责。它允许用户在不修改原始对象的基础上,通过添加装饰类来扩展对象的功能。

结构不同:

  • 适配器模式 包含以下角色:

    • 目标接口(Target):希望适配的接口。
    • 适配者(Adaptee):需要适配的类。
    • 适配器(Adapter):通过在内部包装一个适配者对象,把源接口转换成目标接口。
  • 装饰者模式 包含以下角色:

    • 抽象组件(Component):定义了被装饰接口。
    • 具体组件(ConcreteComponent):实现了抽象组件的具体类。
    • 抽象装饰者(Decorator):抽象类,实现了装饰接口,并持有一个装饰接口的引用。
    • 具体装饰者(ConcreteDecorator):实现抽象装饰者,添加额外的职责。

使用场景不同:

  • 适配器模式 常用于以下场景:

    • 需要将一个已有的类集成到一个新系统中,但接口不兼容。
    • 需要复用一些已有的类,但这些类的接口与新系统的接口不一致。
  • 装饰者模式 常用于以下场景:

    • 需要动态地给对象添加职责,同时希望避免使用继承带来的耦合。
    • 需要通过一种灵活的方式来扩展对象的功能,同时保持对象的开放封闭原则。

行为不同:

  • 适配器模式 通常只关注于接口的转换,不涉及对象功能的扩展。

  • 装饰者模式 允许通过多个装饰者的嵌套使用,来逐步添加多个职责,形成一种链式结构。

示例:

  • 适配器模式示例:假设有一个第三方音乐播放器类ThirdPartyMusicPlayer,它有一个playMusic()方法。你的系统需要一个play()方法的接口。可以创建一个适配器MusicPlayerAdapter,它实现了play()方法,内部调用ThirdPartyMusicPlayerplayMusic()方法。

  • 装饰者模式示例:假设有一个Coffee类,有一个cost()方法返回咖啡的价格。为了添加如加糖、加牛奶等额外服务,可以创建一个装饰者CoffeeDecorator,它持有一个Coffee对象的引用,并在调用cost()方法时添加额外的费用。

总结来说,适配器模式主要用于接口转换,而装饰者模式主要用于对象功能的动态扩展。两者虽然都可以用于复用已有的代码,但它们关注的问题和实现方式是不同的。

这篇关于持续总结中!2024年面试必问 20 道设计模式面试题(四)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1073484

相关文章

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

Spring 依赖注入与循环依赖总结

《Spring依赖注入与循环依赖总结》这篇文章给大家介绍Spring依赖注入与循环依赖总结篇,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. Spring 三级缓存解决循环依赖1. 创建UserService原始对象2. 将原始对象包装成工

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL

精选20个好玩又实用的的Python实战项目(有图文代码)

《精选20个好玩又实用的的Python实战项目(有图文代码)》文章介绍了20个实用Python项目,涵盖游戏开发、工具应用、图像处理、机器学习等,使用Tkinter、PIL、OpenCV、Kivy等库... 目录① 猜字游戏② 闹钟③ 骰子模拟器④ 二维码⑤ 语言检测⑥ 加密和解密⑦ URL缩短⑧ 音乐播放

Spring Boot 与微服务入门实战详细总结

《SpringBoot与微服务入门实战详细总结》本文讲解SpringBoot框架的核心特性如快速构建、自动配置、零XML与微服务架构的定义、演进及优缺点,涵盖开发环境准备和HelloWorld实战... 目录一、Spring Boot 核心概述二、微服务架构详解1. 微服务的定义与演进2. 微服务的优缺点三

Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式

《Java通过驱动包(jar包)连接MySQL数据库的步骤总结及验证方式》本文详细介绍如何使用Java通过JDBC连接MySQL数据库,包括下载驱动、配置Eclipse环境、检测数据库连接等关键步骤,... 目录一、下载驱动包二、放jar包三、检测数据库连接JavaJava 如何使用 JDBC 连接 mys

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的