设计模式-门面模式

1. 简单的门面设计模式的使用

1.1 首先实现一个统一的门面的接口,实现一个Start 方法

java 复制代码
package club.shengsheng.insight.input;

public interface ServerFacade {

     void start() ;
}

1.2 具体的类继承这个接口,实现start方法

java 复制代码
package club.shengsheng.insight;

import club.shengsheng.insight.input.ServerFacade;

public class MySQL implements ServerFacade {

    void initData(){
        System.out.println( "初始化MYSQL" );
    }

    void checkLog(){
        System.out.println("校验日志,恢复可能没有提交的数据");
    }

    void unlock(){
        System.out.println("释放锁");
    }


    void listenPort(){
        System.out.println("监听端口");
    }

    @Override
    public void start() {
        this.initData();

        this.checkLog();

        this.unlock();

        this.listenPort();

    }
}

2 Maven 插件的API就是 maven 的门面,接下来使用门面模式 实现自定义插件的热加载

java 复制代码
// 首先在一个项目中定义出插件的API

public interface MyPlugin {

    void beforeGetTime() ;
}



public class Main {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

目录如下

2.1 具体的插件工程 引入这个依赖,实现具体的插件逻辑

java 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>count_plugin</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.example</groupId>
            <artifactId>my_plugin_api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

    </dependencies>

</project>

2.2 实现这个依赖工程

工程架构


2.3 继承MyPlugin 接口 实现 方法

java 复制代码
package org.example.insight;
import java.util.concurrent.atomic.AtomicInteger;

public class CountPlugin implements MyPlugin {

    AtomicInteger count = new AtomicInteger(0);

    @Override
    public void beforeGetTime() {
        System.out.println("CountPlugin beforeGetTime count: "+count.incrementAndGet() );
    }
}

2.3 实现这个依赖工程 , 实现一个计数的逻辑

同时在resources的资源目录中写出相应的接口相对类路径

2.4 一个SpringBoot工程中引入这个计数插件的依赖,并实现一个http接口、使用反射实现对插件字节码的动态加载

java 复制代码
@RestController
@RequestMapping("/test")
public class TestController {

    @Resource
    private ThreadLocal<Integer> localInt;


    private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    private MyPlugin plugin;

    @GetMapping("/time")
    public String getTime() {

        if(plugin != null) {
            plugin.beforeGetTime();
        }

        return LocalDate.now().format(dateTimeFormatter);
    }

    // 实现了我们插件的jar包,这个文件叫做 genyon.plugin  这个文件的内容就是实现myPlugin的全类名
    // 加载插件的接口 count_plugin-1.0-SNAPSHOT.jar
    // 门面设计模式
    @GetMapping("/pluginLoad/{path}")
    public String loadPlugin(@PathVariable("path") String path  ) {
        File file = new File(path);
        try (URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{file.toURI().toURL()});
             InputStream systemResourceAsStream = urlClassLoader.getResourceAsStream("genyon.plugin");) {

            String fullClassName = new String(systemResourceAsStream.readAllBytes());
            Class<?> abc = urlClassLoader.loadClass(fullClassName.trim());
            Constructor<?> constructor = abc.getConstructor();
            // 实现的my plugin的jar包的对象
             plugin = (MyPlugin) constructor.newInstance();


            return "记载成功: "+ plugin.toString();
        }catch (Exception e) {
            return "加载失败: "+ e.getMessage();
        }
    }

2.5 并将插件打包后放入 SpringBoot工程目录的相对路径中。

2.6 调用接口实现 动态加载,

  1. 首先调用pluginLoad接口 实现 对插件的动态加载

结果如下

  1. 调用相应的第一返回当前时间戳的接口,可以看到返回了时间戳前,还打印了计数插件的计数结果,说明插件顺利加载。

任何一个大的插件项目的原理都是如此,都是先定义一个插件,让第三方实现这个插件,我们通过约定将插件加载进来,并实现一些相应的功能。

相关推荐
绅士玖6 小时前
JavaScript 设计模式之单例模式🚀
前端·javascript·设计模式
凤山老林7 小时前
Spring Boot中的中介者模式:终结对象交互的“蜘蛛网”困境
java·spring boot·后端·设计模式·中介者模式
找了一圈尾巴9 小时前
设计模式(结构型)-适配器模式
设计模式·适配器模式
vvilkim9 小时前
单例模式详解:确保一个类只有一个实例
单例模式·设计模式
CodeWithMe9 小时前
【读书笔记】《C++ Software Design》第六章深入剖析 Adapter、Observer 和 CRTP 模式
c++·设计模式
归于尽10 小时前
从本地存储封装读懂单例模式:原来这就是设计模式的魅力
前端·javascript·设计模式
海底火旺10 小时前
单例模式的实现
前端·javascript·设计模式
3Katrina10 小时前
《JavaScript单例模式详解:从原理到实践》
前端·javascript·设计模式
Code季风11 小时前
测试驱动开发(TDD)实战:在 Spring 框架实现中践行 “红 - 绿 - 重构“ 循环
java·驱动开发·后端·spring·设计模式·springboot·tdd