2017-02-22 99 views
3

所以情况如下:我创建了一个多人游戏,并且我希望我的朋友......能够为它创建漫游器。所以我要做的是创建一个abstract class Bot{},并为机器人定义函数,然后他们必须实现它们:非常简单。获取继承其中一个的第三方类的实例

我卡在哪里,我该如何将它们添加后?你可以使用反射或类似的东西来找到Bot的所有继承者?或者我需要搜索.jar文件?

直到现在,这里是我是如何做到的(简化,类不是在同一个文件等):

abstract class Bot{ 
    public int play(); 
    //... 
} 

class Bot1 extends Bot{ 
    @override 
    public int play(){/*do stuff*/} 
    //... 
} 

,然后当我需要在每个机器人之一:

ArrayList<Bot> bots = new ArrayList<>(); 
bots.add(new Bot1()); 
//... 

我的问题是,如果我要使用这个,因为 instanciation是硬编码的,我需要允许人们修改我的代码来添加他们自己的机器人 - 我不想。

我的问题是,如何在不硬编码的情况下实现这一点?我知道这是可能的,正如Minecraft所做的那样(mods等),但我不知道如何去做。到目前为止,我的研究没有得到任何结果(可能是因为我不知道如何用简单的句子来解释这个问题......),所以欢迎任何提示的线索,以及学习如何去做的地方。

另外,我有OOP和这样的一个很好的理解,但我完全陌生的反射和getClass()东西...

+0

很多想法在这里:http://stackoverflow.com/questions/492184/how-do-you-find-all-subclasses-of-a-given-class-in-java – dnault

+0

此外:http:///stackoverflow.com/questions/465099/best-way-to-build-a-plugin-system-with-java – dnault

+0

查看工厂设计模式。然后你可以使用'reflection'来加载类。 – ahoxha

回答

4

做到这一点(没有任何外部框架)最简单的方法可能是定义Bot的接口(SPI,服务提供商接口),然后使用JRE附带的内置Service Loader机制。自定义Bot实现将需要部署(作为JAR),以便它们可以在您的应用程序的类路径中访问。

所以,像这样:

SPI合同:

public interface Bot { 
    int play(); 
} 

执行(这需要打包成具有作为链接文件中指定,包括META-INF文件夹的目录结构的JAR) :

public class MyBot implements Bot { 
    @Override 
    public int play() { 
     // do something 
    } 
} 

查找:

import java.util.ServiceLoader; 

public class BotResolver { 

    private final ServiceLoader<Bot> loader; 

    public BotResolver() { 
     loader = ServiceLoader.load(Bot.class); 
    } 

    /** 
    * Gets all bot implementations that are currently available in the classpath. 
    */ 
    public List<Bot> getAllBots() { 

     List<Bot> allBots = new ArrayList<>(); 
     Iterator<Bot> it = loader.iterator(); 

     while (it.hasNext()) { 
      allBots.add(it.next()); 
     } 

     return allBots; 
    } 
} 
1

从我的话题How do you find all subclasses of a given class in Java?在看过了,似乎没有真正的除了在每个课程中“蛮力”你的方式,同时检查它是否是Bot的一个子类之外,还有其他方法可以做到这一点。

要回答你的问题,这是可能的,它是在上述主题中描述!

0

如果您使用Spring,您可以请求使用@Component注释Bot实现,以便您的应用程序可以使用组件扫描,然后使用@Autowired private List<Bot> bots;来访问它们。

+0

我一直在使用Netbeans不到一个月的时间,所以(假设Spring是@评论),我对此尚未见过。感谢您的提示,但我会尽快检查。 – CLOVIS

2

这可能不是你所要求的,但是在运行时试图找出给定类的所有子类似乎并不是一个好主意。 为什么不提供你的朋友的工厂登记他们Bot情况下,他们希望通过一个单说:

public enum BotHolder { 
    BOTS; 

    private final List<Bot> bots = new ArrayList<>(); 

    public void registerBot(Bot bot) { 
     bots.add(bot); 
    } 

    public List<Bot> get() { 
     return bots; 
    } 
} 
1

Mick很好的回答。

这是我的解决方案(不使用ServiceLoader API,但使用类似的方法)。

  1. 声明,随后用 你的朋友的僵尸类的完全合格的路径属性名称BotClasses=属性文件。

BOT:

  • 遍历BotClasses属性值用分隔符分割,然后对每个完整的类名使用(多 班由像;一些分隔符分割它们) newObj =(Bot) Class.forName(strFullyQualifiedClassName).newInstance();

  • 只有在Bot实现中存在缺省/非参数构造函数时,此工作才有效。

    1

    你可以让你的朋友创建他们的bot类来实现你的Bot界面,然后把它们全部放在一个文件夹中并使用classLoader.loadClass加载文件夹中的每个类。使用instanceof来检查每个类是否实现了所需的接口,如果它们没有,则丢弃它们。 我写了一个简单的插件系统在本周早些时候尝试了这一点,但现在还没有访问代码,但是如何使用所有这些元素的信息已经可用,祝你好运!

    相关问题