Java包失败了

时间:2013-04-03 02:30:06

标签: java packages

好的,我习惯于像这样构建我的项目

|--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中是否可以使用这样的结构?

4 个答案:

答案 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.jarmyproject-foo.jarmyproject-bar.jar

如果你正在寻找一个更迂腐的组织you should look at this guys blog,但你无法真正强制执行它(就像你在C#中那样),而不是分成单独的项目。

您还应该熟悉canonical Java SPI practicedependency 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中不可能这样做。外部库可以使用相同的应用程序包创建一个类,它将具有包可见性。