好的,我习惯于像这样构建我的项目
|--com.mycompany.interfaces
| |--IFoo1(public)
| |--IFoo2(public)
| |--IBar1(public)
| |--IBar2(public)
|
|--com.mycompany.foos.impl
| |--Foo1(default) implements IFoo1
| |--Foo2(default) implements IFoo2
|
|--com.mycompany.bars.impl
| |--Bar1(default) implements IBar1
| |--Bar2(default) implements IBar2
|
|--com.mycompany.services
| |-FooBarService (public)
我有一个包来组织所有接口,然后实现在他们自己的相关pacakges中。
公共类FooBarService必须通过它们的接口IFoo1,IFoo2等将Foo1,Foo2等实例返回给该项目外的调用者。但是类FooBarService无法访问具体类Foo1,Foo2等,因为它们是包作用域。
什么是不将具体类暴露给外部库的好方法,但是stil将实现保留在有意义的多个包中?或者甚至可能吗?在.net中,我可以将具体类指定为internal
,无论它们是在哪里实现,也不管它们的命名空间是什么,但我想知道在java中是否可以使用这样的结构?
答案 0 :(得分:2)
首先,你真的需要所有这些接口吗?除非你构建一个框架,库,或者你预见到多个实现,所以不要去制作接口,因为它看起来像是好的设计。使用现代AOP和模拟库以及可以像魅力一样重构的IDE,制作数百个接口几乎没有什么好处。特别是(恕我直言)愚蠢的是为每个Java Bean POJO创建一个接口来隐藏特殊(或所有)设置器。我知道这似乎是好的设计,但KISS更好。
让我们假设你这样做。 您应该使用项目依赖性来处理包可见性。这是制作多个项目的最佳方式,例如一个multi module maven project。
类似
myproject
| | myproject-api // interfaces here, depends on pretty much nothing
| | | src
| | | pom.xml // or build.xml or whatever
| | myproject-foo // implementations here, depends on myproject-api
| | | src
| | | pom.xml // or build.xml or whatever
| | myproject-bar //implementations here, depends on myproject-api and maybe foo.
| | | src
| | | pom.xml // or build.xml or whatever
| pom.xml // or build.xml or whatever
myproject构建将生成三个不同的jar(名称可能不同):myproject-api.jar
,myproject-foo.jar
,myproject-bar.jar
如果你正在寻找一个更迂腐的组织you should look at this guys blog,但你无法真正强制执行它(就像你在C#中那样),而不是分成单独的项目。
您还应该熟悉canonical Java SPI practice和dependency injection(现在已经标准化了@Inject
)。
我真的不建议您为服务执行@his static method factory pattern(特别是实例化接口实例)。如果你这样做,最好的情况是service locator pattern但是更糟糕的事情可能发生在开发人员将构造函数中的依赖对象(即聚合构造模式)连接起来并且有时你最终会使用邪恶的单例模式。最后,静态方法始终可用,导致不可预测的使用和生命周期(与DI相比)。
如果你真的喜欢冒险,你可以go look at OSGI。
无论SPI和OSGI如何,我强烈推荐使用多模块方法。
答案 1 :(得分:1)
我对一个包中的每个接口的分离感到不满意,实现在不同的包中按类型分开"。我将实现和接口放在一个包中,并通过功能进一步分离。但你当然有充分的理由。
除了"大"解决方案(像OSGi这样隐藏除发布接口之外的任何模块的系统)你只能隐藏具有工厂和内部类的concrecte类。关键是将工厂放在impl
包中,并使具体类成为工厂的内部类。工厂显然仍然可以看到外部,但重点是防止程序员使用具体实现的具体细节,这不是问题。
所以:
package com.mycompany.foos.impl
public class FooFactory {
private static class FooImpl implements IFoo1 {
...
}
public static IFoo getFoo() {
return new FooImpl();
}
}
如果您的目的是阻止对类的深入检查,那么它确实可以用纯Java来完成;它不是可见性修饰符的目的;并需要一些模块系统。但即便如此,这个班级也可以通过反思进行检查。
答案 2 :(得分:0)
您需要有一个工厂类,它将返回实现实例。
像
这样的东西if(requestedClass.equals("IFoo1"))
return(IFoo1)new Foo1();
答案 3 :(得分:-1)
在Java中不可能这样做。外部库可以使用相同的应用程序包创建一个类,它将具有包可见性。