首先我不知道如何打电话给我的问题,所以任何有关更好标题的建议请告诉我。
我想创建一个接口,以便其他人可以添加他们的实现,然后在运行时决定使用哪个实现。
即。 我创建了一个界面“食物”,并存在2个实现“早餐”和“午餐”。在实现中,两者具有相同的方法名称和相同的参数,我想让用户在运行时调用它们中的任何一个。 “makeFood()使用Breakfast”或“makeFood()使用午餐”。
一种可能性是仅编译一个实现,但如果将来必须使用其他实现,则需要删除.class文件。
或者我应该使用某种类型的继承?
另外(不是优先权): 我不知道实现类名,所以有人可以创建“晚餐”或“secondBreakfast”。这会让我陷入另一个困境,如果用户请求尚未实现的“类”该怎么办:S我总是可以假设用户将知道哪些实现可用。
答案 0 :(得分:4)
这听起来像战略模式将满足您的需求(GOF - http://en.wikipedia.org/wiki/Strategy_pattern)。
我不清楚你想要它有多动态。有两个接口实现,以及一个选择之间的选择器方法是最简单的。但是你也可以动态地动态生成接口的实现,这可能会在这里过度杀死你。无论哪种方式,策略模式都可以抽象出这种复杂性,并使您能够根据所需的任何运行时条件选择不同的行为。
这是一个动态加载类的示例,假设您已经知道完全限定的类名,并且该对象具有无arg构造函数:
Class c = Class.forName("java.lang.Object");
Object o = c.newInstance();
System.out.println( "o = " + o );
此案例需要捕获的错误包括:InterruptedException,ClassNotFoundException,IllegalAccessException,InstantiationException;很多,但只是以同样的方式处理它们并拒绝用户选择。
如果你需要一个带参数的构造函数,那么:
Class c = Class.forName("java.lang.String");
Constructor cons = c.getConstructor( String.class ); // the args here are the expected types for the constructor that you require on the class
String s = (String) cons.newInstance( "hello" );
这将添加更多必须捕获的异常:InterruptedException,ClassNotFoundException,IllegalAccessException,InstantiationException,NoSuchMethodException,InvocationTargetException。但是,再次以与以前相同的方式拒绝用户选择。
答案 1 :(得分:1)
如果您不知道类名并希望了解所有可用的类,则需要在运行时获取接口的所有实现。 这可以通过思考来实现:http://code.google.com/p/reflections/
查看方法getSubTypesOf
如果您希望用户提供自己的实现并使用此实现,您有不同的选择:
1)在启动时读取提供的Jar,并使用依赖注入和预先配置的安装程序(例如使用Spring)。用户可以在启动应用程序之前将完全qialified类名写入设置。
2)使用插件机制,如ServiceLoader:http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html或JSPF:http://code.google.com/p/jspf/。
或者如果你想在运行时阅读新的实现,你可以使用OSGi:http://en.wikipedia.org/wiki/OSGi(看看Apache Karaf,Eclipse Equinox和Apache Felix)。
答案 2 :(得分:0)
您似乎正在描述Java的interface
。例如:
Food.java:
interface Food {
void makeFood();
}
Breakfast.java:
class Breakfast implements Food {
void makeFood() { System.out.println("Breakfast."); }
}
Lunch.java:
class Lunch implements Food {
void makeFood() { System.out.println("Lunch."); }
}
正如您所说,我们有Food
的两种不同实现。现在,我们可以通过构造任一实现类来实例化Food
对象:
Food myFood = new Breakfast();
或
Food myFood = new Lunch();
没有删除文件或类似内容。希望能让事情变得更加清晰。