设计模式-门面/外观模式
门面模式(Facade Pattern)是一种结构型设计模式,它通过提供一个统一且简化的高级接口,隐藏复杂子系统的内部细节,从而让客户端能够以更简单、更直观的方式与子系统进行交互,而无需深入了解其复杂的实现逻辑。
在实际应用中,门面模式被广泛用于简化复杂系统的操作。例如:
SLF4J日志门面:SLF4J(Simple Logging Facade for Java)是一个日志门面框架,它为各种日志框架(如Log4j、Logback等)提供了一个统一的接口。通过SLF4J,开发者可以在代码中使用统一的日志记录方式,而无需关心底层具体使用的是哪种日志实现。这种设计不仅简化了日志记录的使用方式,还使得在不同日志框架之间切换变得极为方便,极大地提高了开发效率和系统的可维护性。
JDBC数据库连接门面:在Java中,JDBC(Java Database Connectivity)提供了与数据库交互的接口。然而,直接使用JDBC进行数据库操作往往涉及到复杂的代码,如数据库连接管理、SQL语句执行和结果处理等。通过引入一个JDBC门面类,可以封装这些复杂的逻辑,为客户端提供一个简单、统一的接口来执行数据库操作。
你的项目也能支持插件
我们来实现一个小demo
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//getTime方法,返回格式化后的当前时间
@GetMapping("/time")
public String getTime(){
return LocalDateTime.now().format(dateTimeFormatter);
}
现在我们需要写一个插件,实现功能:在控制台打印出getTime方法的调用次数
插件是给第三方提供的,为了更好地把这个插件打包,我们新建一个名为my_plugin_api的项目
写一个接口:
public interface MyPlugin {
void beforeGetTime();
}
把myPlugin这个包install到本地

在demo中引入依赖坐标
<dependency>
<groupId>org.example</groupId>
<artifactId>my_plugin_api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
controller中添加成员变量myPlugin
private MyPlugin myPlugin;
然后,我们写一个接口来加载插件
@GetMapping("/loadPlugin/{path}")
public String loadPlugin(@PathVariable("path") String path){
File file = new File(path);
try(URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{file.toPath().toUri().toURL()});
//约定:实现了我们插件的jar包必须有一个文件叫做mss.plugin,这个文件的内容就是实现了MyPlugin接口的实现类的全类名
InputStream mssFile = urlClassLoader.getResourceAsStream("mss.plugin");){
String myPluginFullClassName = new String(mssFile.readAllBytes());
Class<?> aClass = urlClassLoader.loadClass(myPluginFullClassName.trim());
Constructor<?> constructor = aClass.getConstructor();
myPlugin = (MyPlugin) constructor.newInstance();
return "加载成功" + aClass.getName();
}catch (Exception e){
return "加载失败";
}
}
什么有些代码要放到
try()的括号中,而不是花括号{}中?自动关闭资源
try-with-resources语句的核心作用是自动关闭实现了AutoCloseable接口或其子接口Closeable的资源。这些资源通常在try的括号()中声明,而不是在花括号{}中。当try代码块执行完毕(无论是正常结束还是异常退出),try-with-resources会自动调用资源的close()方法。
现在我们再创建count_plugin项目
导入插件api的坐标
实现beforeGetTime方法
public class CountPlugin implements MyPlugin {
AtomicInteger count = new AtomicInteger(0);
@Override
public void beforeGetTime() {
System.out.println(count.incrementAndGet());
}
}
按照约定,我们在resources中创建文件mss.plugin

把这个包打包,就是我们的插件jar包
我们在调用loadPlugin方法的时候要传入路径,但是绝对路径是有url不识别的字符的,所以我们把jar包直接粘到demo的根路径中

跑一下




我们成功让记录次数的插件加载到了正在运行的程序之中(๑˃̵ᴗ˂̵)و
更多推荐

所有评论(0)