Java 如何正确构建多模块项目?

Java 如何正确构建多模块项目?,java,gradle,structure,project,multi-module,Java,Gradle,Structure,Project,Multi Module,这是我在开始新项目时一直在努力解决的问题。所以我决定在这里提问,看看你认为构建这个项目的最佳方式是什么,希望我能从中学到一些东西 这是该项目的基本描述(我使用Gradle btw并用Java编写) 我需要制作一个可以在多个平台上工作的插件,例如spiget、Bungeecord和Velocity,这三个平台都有自己的api,我需要使用它们来让插件在每个平台上工作。 该项目是一个播音器插件,允许用户设置可配置的播音器,向连接到这些服务器的玩家发送消息 我的总体思路是: 通用模块:其中大多数逻辑可应

这是我在开始新项目时一直在努力解决的问题。所以我决定在这里提问,看看你认为构建这个项目的最佳方式是什么,希望我能从中学到一些东西

这是该项目的基本描述(我使用Gradle btw并用Java编写)

我需要制作一个可以在多个平台上工作的插件,例如spiget、Bungeecord和Velocity,这三个平台都有自己的api,我需要使用它们来让插件在每个平台上工作。 该项目是一个播音器插件,允许用户设置可配置的播音器,向连接到这些服务器的玩家发送消息

我的总体思路是:

  • 通用模块:其中大多数逻辑可应用于其他模块 将存储三个模块
  • 插口模块:使用逻辑形成公共模块并将其成形 斯派特能理解
  • 蹦极线模块:使用逻辑形成公共模块,并将其成形 蹦极绳可以理解它
  • 速度模块:使用通用模块的逻辑并将其成形 我能理解
  • project应该具备的一些功能包括:

    • 插件主类,具有逻辑加载和启用插件的功能(每个API都有自己的类,用于扩展主类以启动插件)
    • 文件管理类,该类将从yaml文件加载配置,如播音员消息、常规设置(每个API都有自己的用于读取yaml文件的类)
    • 播音员生成器和处理类,使用文件管理类读取播音员配置文件,并将播音员构建为对象和处理程序,将其发送给播音员等(每个API都有自己与播音员交互的方式)
    • 具有由用户和玩家执行的命令逻辑的命令系统(每个API都有自己的处理命令的逻辑)
    所以我的问题是,如何用最少的可重复代码构建这个项目,复制基本上对每个API做相同事情的类,并且保持良好的代码可读性

    我现在拥有的是一个Spigot的工作版本,但当我开始添加对Bungeecord的支持时,它就变成了一团乱麻

    编辑: 我遇到的一个常见问题示例:

    Spigot API具有
    Bukkit
    类,该类具有返回
    Server
    对象的
    getServer()
    方法。 BungeRecord API有一个
    ProxiedServer
    类,该类具有返回
    ProxiedServer
    对象的
    getInstance()
    方法

    我有这样的想法:

    public interface MyPlugin {
    
        ? getServer();
    }
    
    //extends JavaPlugin is required by Spigot API.
    public class SpigotPlugin extends JavaPlugin implements MyPlugin {
        
        @Overrride
        public ? getServer() {
            return Bukkit.getServer();
        }
    }
    
    //extends Plugin is required by Bungeecord API.
    public class BungeeCordPlugin extends Plugin implements MyPlugin {
     
        @Overrride
        public ? getServer() {
            return ProxiedServer.getInstance();
        }
    }
    
    @Overrride
    public <T> getServer() {
        return plugin.getInstance();
    }
    

    它需要放什么来代替
    来获得正确的服务器实例(我不能编辑
    ProxiedServer
    Bukkit
    类)?

    这已经有几个月了,但为了存档和未来搜索者的利益,我想提供以下内容: 是的,您可以返回类似以下内容的泛型类型:

    public interface MyPlugin {
    
        ? getServer();
    }
    
    //extends JavaPlugin is required by Spigot API.
    public class SpigotPlugin extends JavaPlugin implements MyPlugin {
        
        @Overrride
        public ? getServer() {
            return Bukkit.getServer();
        }
    }
    
    //extends Plugin is required by Bungeecord API.
    public class BungeeCordPlugin extends Plugin implements MyPlugin {
     
        @Overrride
        public ? getServer() {
            return ProxiedServer.getInstance();
        }
    }
    
    @Overrride
    public <T> getServer() {
        return plugin.getInstance();
    }
    
    @override
    公共getServer(){
    返回plugin.getInstance();
    }
    
    供参考:


    关于泛型的更多信息:

    这已经有几个月了,但为了档案馆和未来的搜索者的利益,我想提供以下信息: 是的,您可以返回类似以下内容的泛型类型:

    public interface MyPlugin {
    
        ? getServer();
    }
    
    //extends JavaPlugin is required by Spigot API.
    public class SpigotPlugin extends JavaPlugin implements MyPlugin {
        
        @Overrride
        public ? getServer() {
            return Bukkit.getServer();
        }
    }
    
    //extends Plugin is required by Bungeecord API.
    public class BungeeCordPlugin extends Plugin implements MyPlugin {
     
        @Overrride
        public ? getServer() {
            return ProxiedServer.getInstance();
        }
    }
    
    @Overrride
    public <T> getServer() {
        return plugin.getInstance();
    }
    
    @override
    公共getServer(){
    返回plugin.getInstance();
    }
    
    供参考:


    关于泛型的更多信息:

    编号的项目听起来像是模块的良好开端,其中2到4是垂直切片。我不确定完全混乱意味着什么,但适配器模式可能会有所帮助。不应该有重复的代码。所谓的mess,我的意思是我有一些方法将
    Object
    作为参数,然后根据插件运行的平台将其强制转换为所需的对象,因此结果是大量的强制转换。我不太喜欢这种方法,我不确定是否应该这样做。我会查看适配器模式谢谢你的建议。这就是适配器模式可以提供帮助的地方。公共类由特定于平台的类包装。平台类知道如何与其平台交互,但使用公共类来获取数据。编号的项听起来像是模块的良好开端,其中2到4是垂直切片。我不确定完全混乱意味着什么,但适配器模式可能会有所帮助。不应该有重复的代码。所谓的mess,我的意思是我有一些方法将
    Object
    作为参数,然后根据插件运行的平台将其强制转换为所需的对象,因此结果是大量的强制转换。我不太喜欢这种方法,我不确定是否应该这样做。我会查看适配器模式谢谢你的建议。这就是适配器模式可以提供帮助的地方。公共类由特定于平台的类包装。平台类知道如何与其平台交互,但使用公共类获取数据。