深入解析:Guava 源码中7种设计模式的实现分析

举报
bug菌 发表于 2024/09/29 21:30:08 2024/09/29
【摘要】 咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~🏆本文收录于「滚雪球学Java」专栏中,这个专栏专为有志于提升Java技能的你打造,覆盖Java编程的方方面面,助你从零基础到掌握Java开发的精髓。赶紧关注,收藏,学习吧!环境说明...

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~


🏆本文收录于「滚雪球学Java」专栏中,这个专栏专为有志于提升Java技能的你打造,覆盖Java编程的方方面面,助你从零基础到掌握Java开发的精髓。赶紧关注,收藏,学习吧!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

前言

在现代 Java 开发中,设计模式作为一种解决复杂问题的编程思想,帮助开发者在编写代码时提供了更加清晰的结构和流程。Google 的 Guava 库是一个广受欢迎的开源 Java 工具包,包含了大量有助于提升开发效率的工具和类库。在设计 Guava 时,开发团队充分利用了设计模式的优势,通过这些模式的合理应用,增强了库的功能性和灵活性。

本文将通过对 Guava 源码中7种经典设计模式的深入分析,展示这些模式在实际应用中的价值,并通过具体的代码示例和详细解释,帮助读者更好地理解这些设计模式的实现和应用场景。


1. 单例模式 (Singleton Pattern)

模式简介

单例模式是一种确保一个类只有一个实例的设计模式,尤其适用于资源密集型对象(如数据库连接、配置管理等)的管理。Guava 在实现中,充分利用了单例模式来提高性能并避免重复创建对象。

Guava 实现分析

Guava 提供的 Suppliers.memoize() 是一个典型的单例模式实现。该方法缓存了一个供应商对象(supplier),确保在第一次调用时创建实例,后续调用直接返回已缓存的对象,避免了重复创建。

Supplier<Object> supplier = Suppliers.memoize(() -> new Object());
Object instance1 = supplier.get();
Object instance2 = supplier.get();
System.out.println(instance1 == instance2); // true

通过 memoize(),我们可以确保供应商只创建一个对象,并在整个程序运行期间重复使用这个对象。这样既节约了内存,也提高了程序的性能。

深度与广度拓展

单例模式虽然简单,但在多线程环境下,使用不当可能会导致并发问题。为了解决这个问题,Guava 的 Suppliers.memoize() 方法内部实现了线程安全机制。通过锁机制或者使用 volatile 关键字,确保即使在多线程环境下也不会重复创建对象。

在实际开发中,单例模式非常常见,比如在 web 应用中,通常会将某些资源密集型服务(如缓存服务、配置服务)设计为单例,确保全局只有一个实例,从而节省资源。此外,单例模式也常常用于日志记录器的实现,确保在整个应用中日志的统一管理。


2. 工厂模式 (Factory Pattern)

模式简介

工厂模式是一种创建对象的设计模式,通过工厂方法代替直接使用构造函数,来决定实例化哪一个类。这种模式特别适合于对象创建逻辑复杂,或者对象类型在运行时动态确定的情况。

Guava 实现分析

Guava 中的 ImmutableListImmutableMap 类均使用了工厂模式来创建不可变集合。通过静态工厂方法 of(),可以方便地创建不可变对象,避免了直接调用构造器的繁琐。

List<String> immutableList = ImmutableList.of("A", "B", "C");
Map<String, Integer> immutableMap = ImmutableMap.of("One", 1, "Two", 2);

通过 ImmutableList.of()ImmutableMap.of(),我们不仅可以快速创建集合,还能确保这些集合是不可变的。这种设计避免了集合被修改的风险,增强了系统的安全性。

深度与广度拓展

在大型软件系统中,工厂模式被广泛应用。Guava 的工厂方法模式使得集合创建更加简洁,特别是在创建不可变集合时,极大简化了开发流程。

工厂模式还可以通过子类化或策略模式扩展,实现更加灵活的对象创建逻辑。比如在数据库连接池管理中,工厂模式常用于动态生成不同数据库类型的连接对象。随着系统的扩展,工厂模式也能适应新的需求,减少对已有代码的修改,从而提高系统的可维护性。


3. 策略模式 (Strategy Pattern)

模式简介

策略模式是一种行为型设计模式,允许在运行时选择不同的算法或策略。通过将不同的算法封装为独立的策略类,程序可以根据需求动态切换策略,而不影响客户端代码。

Guava 实现分析

Guava 的 Ordering 类是策略模式的典型实现之一。Ordering 提供了一系列排序算法,并允许开发者根据需求选择或组合不同的排序策略。比如通过自然排序、反向排序或自定义排序等。

Ordering<String> ordering = Ordering.natural().reverse();
List<String> names = Lists.newArrayList("Adam", "Eve", "John");
Collections.sort(names, ordering);
System.out.println(names); // [John, Eve, Adam]

在这个示例中,Ordering 提供了一种反转排序策略,轻松实现了从自然排序到反向排序的切换。

深度与广度拓展

策略模式的优点在于能够通过组合不同的策略类,灵活应对需求的变化。在实际应用中,支付系统中的多种支付方式处理、图形绘制中的不同绘制算法选择,都可以通过策略模式来实现。

Guava 的 Ordering 类通过一系列方法封装了多种排序策略,不仅提高了代码的可读性,还增强了代码的扩展性和灵活性。开发者可以根据业务需求轻松实现自定义排序,而无需修改原有排序逻辑。


4. 装饰器模式 (Decorator Pattern)

模式简介

装饰器模式允许在不改变对象结构的前提下动态添加功能。这种模式通过将对象包裹在一个装饰器类中,从而实现对原有对象的功能扩展。

Guava 实现分析

在 Guava 中,Collections2.filter() 是一个装饰器模式的经典应用。它为集合添加了过滤功能,而不改变集合本身的数据结构。通过这种方式,开发者可以在不修改原集合的前提下,按需筛选数据。

Collection<String> filtered = Collections2.filter(list, input -> input.startsWith("A"));

这个方法返回一个过滤后的集合视图,原集合保持不变,扩展了集合的功能。

深度与广度拓展

装饰器模式在现实开发中非常常见,如 Java I/O 库中,BufferedReader 就是对 Reader 的装饰,增加了缓冲功能而不改变原有 Reader 的行为。

Guava 的装饰器设计让开发者能够通过一层层包装对象,灵活添加功能而不影响原有代码。这种设计模式非常适用于需要动态增加功能的场景,如用户权限管理系统中的权限验证机制。


5. 观察者模式 (Observer Pattern)

模式简介

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

Guava 实现分析

Guava 提供的 EventBus 就是观察者模式的典型实现。它允许开发者轻松实现事件的发布与订阅,发布者和订阅者之间松耦合。

EventBus eventBus = new EventBus();
eventBus.register(new EventListener());
eventBus.post(new MyEvent("Hello, World!"));

通过 EventBus,开发者可以实现松耦合的事件通知机制,发布者不需要知道具体的订阅者,反之亦然。

深度与广度拓展

观察者模式广泛应用于 GUI 事件处理、消息通知系统等场景。在大型系统中,尤其是在模块间需要进行松耦合通信时,观察者模式是非常理想的选择。

Guava 的 EventBus 使得事件的处理变得更加简单和灵活,大大提高了系统的扩展性和可维护性。在实际开发中,它非常适合用于构建基于事件驱动的系统,如日志处理、用户行为追踪等。


6. 适配器模式 (Adapter Pattern)

模式简介

适配器模式将一种接口转换为客户希望的另一种接口,使得原本由于接口不兼容而无法一起工作的类可以协同工作。

Guava 实现分析

Guava 中的 Function 类可以视为一种适配器,将一种输入类型转换为另一种输出类型。比如通过 Lists.transform() 方法,开发者可以轻松将列表中的元素转换为另一种类型。

List<Integer> lengths = Lists.transform(strings, String::length);

这个例子中,Function<String, Integer> 充当了适配器,将字符串转换为其对应的长度。

深度与广度拓展

适配器模式常用于解决接口不兼容的问题,特别是在系统升级或模块集成时,适配器可以帮助旧系统和新系统无缝协作,减少修改代码的风险。

Guava 的适配器模式实现

使得数据转换过程变得简单、直观,开发者可以通过这种方式轻松处理不同类型之间的转换,提高了代码的可读性和可维护性。


7. 享元模式 (Flyweight Pattern)

模式简介

享元模式通过共享细粒度对象,来减少内存开销。在需要大量细粒度对象时,尤其有效。

Guava 实现分析

Guava 中的 Interners.newWeakInterner() 就是享元模式的典型实现,它缓存对象实例,避免重复创建。

Interner<String> interner = Interners.newWeakInterner();
String s1 = interner.intern(new String("test"));
String s2 = interner.intern(new String("test"));
System.out.println(s1 == s2); // true

通过 intern() 方法,Guava 能够有效地共享相同内容的字符串实例,节省内存。

深度与广度拓展

享元模式适用于需要大量创建相同对象的场景,如对象池、缓存等。在 web 系统中,享元模式可以用于优化会话管理、数据库连接等频繁创建的对象,提升系统性能表现。

对于大型应用,采用享元模式可以显著减少内存使用,优化应用的响应速度。在缓存管理、图形绘制等场景中,享元模式也表现出了良好的性能优势。


结语

Guava 通过广泛应用设计模式,不仅提升了代码的灵活性、可读性和可维护性,还为 Java 开发者提供了诸多实用的功能。掌握 Guava 中的设计模式,可以帮助我们在实际开发中灵活应对复杂的设计需求。

设计模式并不仅仅是理论,而是解决复杂问题的实战工具。通过深入理解 Guava 中的设计模式实现,我们可以更好地运用这些模式,编写出简洁高效且易于扩展的代码。在日常开发中,合理选择设计模式,能够有效提升代码质量,优化系统性能,并简化维护工作。

☀️建议/推荐你

无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学Java」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门Java编程,就像滚雪球一样,越滚越大,指数级提升。

码字不易,如果这篇文章对你有所帮助,帮忙给bug菌来个一键三连(关注、点赞、收藏) ,您的支持就是我坚持写作分享知识点传播技术的最大动力。
  同时也推荐大家关注我的硬核公众号:「猿圈奇妙屋」 ;以第一手学习bug菌的首发干货,不仅能学习更多技术硬货,还可白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有!

📣关于我

我是bug菌,CSDN | 掘金 | infoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,掘金等平台签约作者,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计30w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。


–End

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。