报表组件和日志框架中的工厂模式

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 报表组件和日志框架中的工厂模式

大思接了满满一杯热咖啡,正欲离去,转身时,偶然瞥见茶水间的白板画满了类图,定睛一看,感慨地说道:“蔡了,你还真是幸福啊!马大叔亲自给你讲解工厂模式。”

蔡了刚刚意识到自己说错了话,还在尴尬中,赶紧说道:“是啊,是啊!”一边说着,一边还使劲地点着头,希望通过过分的礼貌来化解刚才的口不择言。

成大思想到了自己过去学习设计模式的经历,悠悠地说道:“说起来,当初我学设计模式时,可没有你这么好的待遇了。”

这一番话倒是勾起了蔡了的好奇心,赶紧问道:“大思,那你当时是怎么学的呢?”

既然有了谈兴,成大思也在沙发坐下来,慢条斯理地说道:“当初我刚入行没多久,就接到一个开发任务,让我独自完成一个报表组件的设计与开发。这一报表组件是公司应用框架的一部分,需要支持微软的水晶报表和用友的华表。说起来,现在的程序员可能都没听说过这两款报表产品了吧。”谈到过去,同样作为职场老人的马丁花似乎深有同感,举起手里的咖啡,如饮酒一般向大思隔空敬过,二人各自仰头吞了大大一口苦涩的浓咖啡,长吁短叹,对视无言,油然而生英雄迟暮之感。

95后的蔡了哪里能体悟IT历史的往昔与荣光,继续如好奇宝宝地追问:“后来呢?”

大思回过神,继续讲道:“我接到任务后,想了许久,也不知该如何设计才能灵活地支持各种报表,无奈之下,只得去寻求项目经理的帮助。项目经理听了我的问题,丢下一句‘用工厂模式可以解决’,然后就酷酷地抛下我不管了。没有办法,好歹给我指点了明灯,于是我就开始上穷碧落下黄泉地寻找工厂模式的资料。那时候,哪有这么多讲解设计模式的资料?主要的参考资料还是GOF的《设计模式》。说起来,虽然这本书的讲解稍显晦涩,但它才是设计模式的正宗心法啊!蔡了,你可以好好读读这本书!”

image.png


蔡了谢过大思的推荐,继续追问:“那你最后是如何设计的呢?”

“真要理解了工厂方法模式,说起来也不难。我对这两种报表进行了抽象,分别定义了报表对象(ReportObject)、报表处理器(ReportProcessor)和报表格式器(ReportFormatter),毫无疑问,它们都具有各自的继承体系,可以引入工厂来创建它们。”

说到这里,大思拿起板擦,问道:“白板上的内容可以擦掉吧?”这时的蔡了倒是学会了察言观色,赶紧抢过大思手中的板擦,说道:“我来!我来!”三下五除二,白板擦得干干净净。大思在白板上画下了这样的类图:

image.png

“这不就是抽象工厂模式吗?”蔡了惊喜地嚷道。

“不错!”成大思答道,“说起来,这一设计方案都过去十多年了,我至今对这一方案依旧历历在目,毕竟这是我第一次独立设计一个组件。”

“所以说,还是要做实际的项目才能锻炼人!”马丁花补充道,然后对蔡了道:“听别人讲授设计知识固然能快速帮助你理清思路,掌握知识窍门,但没有经过你自己的思考,不可能真正掌握,更不用说合理地运用到项目中。这样吧,给你布置一个学习任务,利用业余时间学习slf4j日志框架。我们项目也使用了这一框架,你应该知道它的用法,对吧?”

蔡了点头称是。

马丁花继续说道:“slf4j框架灵活地运用了设计模式,也包括今天提到的工厂模式。针对slf4j如何创建一个Logger,你可以查阅相关资料,并阅读slf4j的源代码,深入了解其设计手段,写一份学习笔记。”

三人结束了这番在茶水间的谈话,留给蔡了的又是一份没法拒绝的学习礼物。


◐◐◐


三天后,蔡了向马丁花交付了一份学习笔记。内容如下:

slf4j本身是一个日志框架,为了让Java开发人员可以采用同一种方式使用日志,它又很好地集成了logback、log4j等其他日志框架。为此,它定义了标准的日志接口,slf4j的slf4j-simple日志框架与logback都实现了日志接口。由于log4j的诞生要早于slf4j,则专门提供了slf4j-log4j12将log4j整合到slf4j中。

不管是什么样的日志框架,只要使用slf4j,都可以通过如下代码来创建Logger:


private final Logger logger = LoggerFactory.getLogger(Demo.class);


LoggerFactory的getLogger()方法就是简单工厂模式的体现。在getLogger()方法内部,具体创建什么样的Logger,又由ILoggerFactory工厂来决定的。ILoggerFactory工厂和它创建的Logger就是slf4j定义的通用日志对象接口。以logback为例,它定义了自己的日志工厂和日志对象,实现了slf4j的接口,如果其他日志框架,如log4j需要slf4j作为统一的日志入口,也需要实现这些接口。

image.png

这实际上是工厂方法模式的体现。

slf4j具体使用了哪一个日志框架,取决于项目依赖的日志包。只要将对应的日志系统jar包加入到项目中,slf4j就会自动选择使用它。例如,倘若添加这样的Maven依赖:


<dependency>    <groupId>org.slf4j</groupId>    <artifactId>slf4j-api</artifactId>    <version>${slf4j.version}</version></dependency><dependency>    <groupId>ch.qos.logback</groupId>    <artifactId>logback-classic</artifactId>    <version>${logback.version}</version>    <optional>true</optional>    <scope>runtime</scope></dependency>


意味着slf4j会使用logback日志框架。

ILoggerFactory对象的创建由slf4j来决定,不需要进行配置,更不需要人为的修改创建代码。怎么才能做到这一点呢?

我仔细阅读了slf4j的源代码,又查阅了相关的资料,发现slf4j具体选择哪一个ILoggerFactory,是由LoggerFactoryBinder决定的,可以将它理解为是日志工厂的工厂,在slf4j框架中,将其形象地称之为一种绑定(bind)操作。

根据这一设计,我最初以为slf4j要通过反射创建不同日志框架的LoggerFactoryBinder对象,后来发现LoggerFactoryBinder接口只有一个实现类,即StaticLoggerBinder。LoggerFactory调用了它的getSingleton()方法获得StaticLoggerBinder对象,再由此获得ILoggerFactory工厂:


StaticLoggerBinder.getSingleton().getLoggerFactory()


我翻阅了成大思推荐的《设计模式》,了解到创建StaticLoggerBinder对象的这种方式称之为单例模式。我站在调用者的角度去思考,发现这一设计可以高效地获得StaticLoggerBinder对象,因为它可以避免对象的频繁创建。

由于getSingleton()是StaticLoggerBinder的静态方法,因此LoggerFactory对它是类型依赖的,做不到实例方法的多态扩展。实际上,这个类的名称也说明了它采用了静态方式绑定了日志工厂。这就要求所有实现了slf4j接口的日志框架,都需要定义这个类,且这个类的classpath应该保持一致。在slf4j的LoggerFactory中定义了这个类的路径:


private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";

查看logback的JAR包,确实在指定位置发现了该类:

image.png

◐◐◐

马丁花收到这份作业后,不禁抓了抓日渐稀薄的头发,心里哀叹,要培养一个新人,还有很长的一条路要走啊!是否让蔡了继续深入研究slf4j这一框架呢?马丁花陷入了沉思中。

image.png

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
24天前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
176 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
2月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
256 3
|
2月前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
106 1
|
3月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
49 2
|
2月前
|
SQL XML 监控
SpringBoot框架日志详解
本文详细介绍了日志系统的重要性及其在不同环境下的配置方法。日志用于记录系统运行时的问题,确保服务的可靠性。文章解释了各种日志级别(如 info、warn、error 等)的作用,并介绍了常用的日志框架如 SLF4J 和 Logback。此外,还说明了如何在 SpringBoot 中配置日志输出路径及日志级别,包括控制台输出与文件输出的具体设置方法。通过这些配置,开发者能够更好地管理和调试应用程序。
|
2月前
|
缓存 Linux 编译器
【C++】CentOS环境搭建-安装log4cplus日志组件包及报错解决方案
通过上述步骤,您应该能够在CentOS环境中成功安装并使用log4cplus日志组件。面对任何安装或使用过程中出现的问题,仔细检查错误信息,对照提供的解决方案进行调整,通常都能找到合适的解决之道。log4cplus的强大功能将为您的项目提供灵活、高效的日志管理方案,助力软件开发与维护。
62 0
|
3月前
|
Java
日志框架log4j打印异常堆栈信息携带traceId,方便接口异常排查
日常项目运行日志,异常栈打印是不带traceId,导致排查问题查找异常栈很麻烦。
|
3月前
|
运维 NoSQL Java
SpringBoot接入轻量级分布式日志框架GrayLog技术分享
在当今的软件开发环境中,日志管理扮演着至关重要的角色,尤其是在微服务架构下,分布式日志的统一收集、分析和展示成为了开发者和运维人员必须面对的问题。GrayLog作为一个轻量级的分布式日志框架,以其简洁、高效和易部署的特性,逐渐受到广大开发者的青睐。本文将详细介绍如何在SpringBoot项目中接入GrayLog,以实现日志的集中管理和分析。
262 1
|
4月前
|
消息中间件 监控 搜索推荐
OpenFeign日志组件Logger原理与应用
该文章详细解释了如何在OpenFeign中配置并使用请求和响应的GZIP压缩功能。
|
4月前
|
XML Java Maven
Spring5入门到实战------16、Spring5新功能 --整合日志框架(Log4j2)
这篇文章是Spring5框架的入门到实战教程,介绍了Spring5的新功能——整合日志框架Log4j2,包括Spring5对日志框架的通用封装、如何在项目中引入Log4j2、编写Log4j2的XML配置文件,并通过测试类展示了如何使用Log4j2进行日志记录。
Spring5入门到实战------16、Spring5新功能 --整合日志框架(Log4j2)