// interface defined in Coffee.jar.
interface Coffee {
void brew();
void discard();
}
// implementation defined in BlackCoffee.jar
class BlackCoffee implements Coffee {
@Override
public void brew() {
System.out.println("Brew BalckCoffee");
}
@Override
public void discard() {
System.out.println("Discard BlackCoffee");
}
}
// implementation defined in FilterCoffee.jar
class FilterCoffee implements Coffee {
@Override
public void brew() {
System.out.println("Brew FilterCoffee");
}
@Override
public void discard() {
System.out.println("Discard FilterCoffee");
}
}
// Runtime class in Coffee.jar
class BrewCoffee {
public static void main(String[] args) {
Coffee coffee = //something here;
coffee.brew();
coffee.discard();
}
}
然后,在不知道实现的情况下在运行时解析实现。该应用程序的依赖项是coffee.jar,依赖项来自blackcoffee.jar或filtercoffee.jar。
2条答案
按热度按时间v6ylcynt1#
这是依赖注入框架(如spring)的优点之一。
您编写了接口代码,而您的客户机类不知道在运行时示例化了哪个实现。
您可以根据条件选择哪一个,例如在spring中可以使用@conditional属性
然后有
然后在spring的属性中,您可以定义属性“black”或“filter”来激活两个具体类实现中的一个。如果您同时定义了这两个属性,您将得到一个异常,说明存在两个coffee示例,并且它不知道将哪个(依赖注入)注入到您的应用程序中
ClassUsingCoffee
班如果不深入了解spring的细节,很难解释。但你也可以用
ApplicationContext
(把它想象成一个包含spring所知道的所有类的“东西”)在这两个示例中,您都将类与
Coffee
接口而不是具体的实现。e、 如果你做了Coffee coffee = new BlackCoffee()
然后您的代码被耦合到coffee的特定实现(在本例中)BlackCoffee
)任何需要的更改都需要代码更改(与配置/属性更改相反)qij5mzcb2#
如果您希望选择接口的实现,因为类路径上存在实现的jar文件,那么您应该使用服务加载器框架。
查看java™ 教程-创建可扩展的应用程序以获取更多信息。
在您的情况下,首先组织代码,即将类放入包中:
然后像这样 Package :
放
com/example/api/Coffee.class
在文件中coffee.jar
放com/example/black/BlackCoffee.class
在文件中black.jar
与文件一起META-INF/services/com.example.api.Coffee
有内容的com.example.black.BlackCoffee
放com/example/filter/FilterCoffee.class
在文件中filter.jar
与文件一起META-INF/services/com.example.api.Coffee
有内容的com.example.filter.FilterCoffee
放com/example/BrewCoffee.class
在文件中brew.jar
现在可以使用以下命令之一运行程序:注意:在linux上,替换
;
与:
自从main
方法在所有实现中循环,第三个命令将同时运行这两个实现BlackCoffee
以及FilterCoffee
.