Java—通过添加新类而不修改任何其他内容来添加功能

Java—通过添加新类而不修改任何其他内容来添加功能,java,reflection,Java,Reflection,如何使类A、B、C具有功能F,然后将类D添加到bin/并获得与F不同的功能,而不以任何方式修改A、B或C 我在Minecraft上看到过这种情况。使用ModLoader,您可以将类从ModLoader复制到Minecraft。然后,您可以简单地将一个以“mod_2;”开头的新类放入Minecraft jar,它会为游戏添加新的内容。在任何时候都没有直接引用“mod_Foobar”类的类 最好是一个小的工作示例和指向任何进一步阅读的链接。类路径用于加载类,并且是有序的,因此如果您将类放在原始类之前

如何使类
A
B
C
具有功能F,然后将类
D
添加到
bin/
并获得与F不同的功能,而不以任何方式修改
A
B
C

我在Minecraft上看到过这种情况。使用ModLoader,您可以将类从ModLoader复制到Minecraft。然后,您可以简单地将一个以“mod_2;”开头的新类放入Minecraft jar,它会为游戏添加新的内容。在任何时候都没有直接引用“mod_Foobar”类的类


最好是一个小的工作示例和指向任何进一步阅读的链接。

类路径用于加载类,并且是有序的,因此如果您将类放在原始类之前,您的类将被加载,而不是原始类。

我想这都是关于应用基本OO原则的

简单的继承允许您实现。在设计良好的系统中,这是将新行为引入系统的良好起点

是工具箱中的另一种软件设计模式,可以在运行时选择算法的行为

(结合反射和上面提到的模式)可以创建一个系统,在这个系统中,您可以将类“删除”到现有系统中,以便在不更改其核心的情况下添加新功能

您还可以在启动时查找有趣的(带注释的)类来修改运行时行为

我相信MindCraft是一个设计良好的系统,应用了比这里描述的更多的模式

最终,这一切归结为良好的设计和在正确的位置应用正确的模式

public class Reflection {

    public void sayHello(String theClass){
        //Since Mod classes are in package 'mod', we precede their name accordingly.
        Class aClass = Class.forName("mod." + theClass);
        aClass.getMethod("sayHi").invoke(aClass.newInstance());
    }

    public static void main(String[] args) {
        //Get a list of the compiled classes in the 'mod' folder
        String path = "./bin/mod";
        String fileName;
        File folder = new File(path);
        List<File> fileList = Arrays.asList(folder.listFiles());
        //Iterate through the list of classes to invoke their methods
        Iterator<File> it = fileList.iterator();        
        while(it.hasNext()){
            fileName = it.next().getName();     
            //When invoking the sayHello method, we remove the file extension
            new Reflection().sayHello(fileName.replace(".class", ""));
        }

    }
}
ModB类:

public class ModB {
    public void sayHi(){
        System.out.println("Hi! I'm ModB.");        
    }   
}
请注意:

  • 为了澄清示例,我删除了一些必要的异常处理
  • Mod类位于名为“Mod”的包中。编译后,它们出现在bin/mod中。也许有一种更干净的扫描方式
  • Mod类被编译、打包到jar中并包含在构建路径中

我标记了
反射
,因为我感觉它牵涉其中(尽管我对它一无所知)。如果你知道它是不相关的,请说出来,或者删除它。我不知道确切的方法,但我认为你应该能够找到你的类路径上的所有类,然后通过反射加载它们。或者您可以找到.class文件并通过某种机制加载它们(javassist应该可以工作,但可能还有其他功能)。Eclipse通过配置文件(即加载它的插件)完成这些事情。等等这一切都会消耗在寻找您可能希望在类路径上使用的文件上。这可能是策略设计模式在起作用吗经过反思,我终于开始明白它的作用。我的问题的答案基本上是:“反思”,我给它贴上了标签。我基本上在标签上回答了我的问题。这个问题过于宽泛。请随意投票结束,因为这“不是一个真正的问题”
public class ModB {
    public void sayHi(){
        System.out.println("Hi! I'm ModB.");        
    }   
}