0%

设计模式应用

总结整理遇到过已经使用过的设计模式

装饰器模式

Java IO 流

1736230771561.png
Java 的输入输出流中使用了装饰器模式,比如可以使用 BufferedInputStream 和 DataInputStream 来装饰几种基本的输入流。更多的例子可以参考 JavaSE(一) IO类层次关系和各种IO流的用法总结 - 有梦想的老王 - 博客园

适配器模式

Java IO 字节流与字符流

IO 流中的字符流和字节流的接口不同,它们之间可以协调工作就是基于适配器模式来做的,通过适配器,我们可以将字节流对象适配成一个字符流对象,这样我们可以直接通过字节流对象来读取或者写入字符数据。

InputStreamReaderOutputStreamWriter 就是两个适配器(Adapter),同时,它们两个也是字节流和字符流之间的桥梁。

  • InputStreamReader 使用 StreamDecoder (流解码器)对字节进行解码,实现字节流到字符流的转换
  • OutputStreamWriter 使用 StreamEncoder(流编码器)对字符进行编码,实现字符流到字节流的转换

SLF4J 适配器

SLF4J 通过适配器模式适配了具体的日志实现(Log4j、Logback 等)

Hippo4j 动态线程池适配器

Hippo4j 通过实现 ThreadPoolAdapter 接口实现对 Dubbo、Spring Cloud、Kafka、RabbitMQ 等第三方线程池的适配。

外观模式(门面模式)

SLF4J

SLF4J 作为日志系统的外观,提供了一个简单的接口来隐藏底层的日志实现。使用者通过 SLF4J API(如 Logger 接口)记录日志,而不需要关心底层实现(Logback、Log4j 等)。

单例模式

SLF4J

SLF4J 的 LoggerFactory 是基于单例模式的,保证只有一个日志工厂示例,其是通过双重校验锁来实现的:

public final class LoggerFactory {  

static final int UNINITIALIZED = 0;
static final int ONGOING_INITIALIZATION = 1;
static final int FAILED_INITIALIZATION = 2;
static final int SUCCESSFUL_INITIALIZATION = 3;
static final int NOP_FALLBACK_INITIALIZATION = 4;
// volatile 保证多线程内存可见性
static volatile int INITIALIZATION_STATE = UNINITIALIZED;

private LoggerFactory() {

}

public static ILoggerFactory getILoggerFactory() {
if (INITIALIZATION_STATE == UNINITIALIZED) {
synchronized (LoggerFactory.class) {
if (INITIALIZATION_STATE == UNINITIALIZED) {
INITIALIZATION_STATE = ONGOING_INITIALIZATION;
performInitialization();
}
}
}
switch (INITIALIZATION_STATE) {
case SUCCESSFUL_INITIALIZATION:
return StaticLoggerBinder.getSingleton().getLoggerFactory();
case NOP_FALLBACK_INITIALIZATION:
return NOP_FALLBACK_FACTORY;
case FAILED_INITIALIZATION:
throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
case ONGOING_INITIALIZATION:
// support re-entrant behavior.
// See also http://jira.qos.ch/browse/SLF4J-97 return SUBST_FACTORY;
}
throw new IllegalStateException("Unreachable code");
}
}

工厂模式

SLF4J Logger factory

SLF4J 通过 LoggerFactory 来生产 Logger

public static Logger getLogger(String name) {
/**工厂方法模式的使用**/
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}
//工厂接口
public interface ILoggerFactory {
Logger getLogger(String var1);
}
//Logger产品接口
public interface Logger {
String ROOT_LOGGER_NAME = "ROOT";
...
}

InLong Sort 模块中的 Flink Connector 采用了工厂模式来制造 Source 对象用于和具体的数据源对接。
1736251041419.png

观察者模式(发布-订阅模式)

Spring Event

Spring Event 事件监听机制就是基于观察者模式实现的,具体可参考解耦利器——观察者模式在spring中的实现一、什么是观察者模式观察者模式定义了一种一对多的依赖关系,让多个观察者对象同 - 掘金

建造者模式(生成器模式)

通过 Builder 类解决复杂的构造参数,通过链式的写法来构造一个 Builder 对象,调用 build 方法后生成目标对象。

OpenTelemetryAppender 构造

为 Apache InLong 项目的 Sort 模块集成 Opentelemetry 的日志上报功能时设计的OpenTelemetryAppender 类就采用了建造者模式,因为有不少属性是可选配置的,这样可以不用为每种情况都编写一个构造函数,而且代码看起来更优雅一些。

代理模式

参考资料

  1. JavaSE(一) IO类层次关系和各种IO流的用法总结 - 有梦想的老王 - 博客园
  2. Java IO 设计模式总结 | JavaGuide