持续总结中!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

相关文章

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最为重要的

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

Nginx Location映射规则总结归纳与最佳实践

《NginxLocation映射规则总结归纳与最佳实践》Nginx的location指令是配置请求路由的核心机制,其匹配规则直接影响请求的处理流程,下面给大家介绍NginxLocation映射规则... 目录一、Location匹配规则与优先级1. 匹配模式2. 优先级顺序3. 匹配示例二、Proxy_pa

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio

MySQL基本查询示例总结

《MySQL基本查询示例总结》:本文主要介绍MySQL基本查询示例总结,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Create插入替换Retrieve(读取)select(确定列)where条件(确定行)null查询order by语句li

Linux区分SSD和机械硬盘的方法总结

《Linux区分SSD和机械硬盘的方法总结》在Linux系统管理中,了解存储设备的类型和特性是至关重要的,不同的存储介质(如固态硬盘SSD和机械硬盘HDD)在性能、可靠性和适用场景上有着显著差异,本文... 目录一、lsblk 命令简介基本用法二、识别磁盘类型的关键参数:ROTA查询 ROTA 参数ROTA