如何在保留封装的同时将代码逻辑组织到包中

时间:2019-05-18 16:33:54

标签: java

这是一个概念性问题。
我通常以逻辑方式将代码组织在软件包中。 例如:数学运算进入my.package.math或业务逻辑进入my.package.business,依此类推。

这几天我怀疑我是否想对Java中程序包可见性施加的约束感到怀疑。

让我展示一些代码来更好地解释我的情况: 我的包装结构如下:

+-- org.example
    +-- greetings
    |   +-- RandomGreetings
    +-- GreetingsService
    |
    +-- Main

和以下代码:

GreetingsService.java

package org.example;

import org.example.greetings.RandomGreetings;

public class GreetingsService {
    public String greetingsToTheWorld(){
        RandomGreetings greetings = new RandomGreetings();
        return greetings.say() + " World";
    }
}

RandomGreetings.java

package org.example.greetings;

import java.util.Random;

class RandomGreetings {
    public String say() {
        Random rand = new Random();
        int value = rand.nextInt(2);
        return value==0 ? "Hello" : "Hi";
    }
}

Main.java

package org.example;

public class Main {

    public static void main(String[] args) {
        GreetingsService sayHelloService = new GreetingsService();
        System.out.println(sayHelloService.greetingsToTheWorld());
    }
}

正如我向您展示的,此代码无法编译,因为类RandomGreetings是包可见的,这意味着GreetingsService无法实例化它。 可以通过将 public 放在类RandomGreetings中来解决此问题:

public class GreetingsService {
...
}

但是对我来说RandomGreetings是一个我想保持封装且不公开的实现。 在这种情况下,世界(任何导入我可能产生的jar工件的人)都可以看到并调用该类,而那并不是我想要的。

另一种可能的解决方案是将GreetingsService移动到相同的RandomGreetings级别,如下所示:

+-- org.example
    +-- greetings
    |   +-- RandomGreetings
    |   |
    |   +-- GreetingsService
    |
    +-- Main

在这种情况下,代码可以成功编译并且RandomGreetings被封装,但是我最终遇到了另一个问题。
我不能再按照逻辑顺序在包中组织该类。
在这种情况下,有几个班级,因此情况仍然可以控制,但是如果班级数量增加,我认为只会有一个独特的大包装。

我知道在Java中没有subpackage visibility,那么如何处理这种情况?
您如何解决上面我的代码的问题?

1 个答案:

答案 0 :(得分:1)

要使用程序包时,它必须具有一些入口点,该入口点必须为public。否则,您将无法使用该包装,将其丢弃。这意味着您的org.example.greetings软件包必须包含public,并且可以从“外部”使用/调用。不必是您的RandomGreetings班。

您可以定义一个接口(在org.example包中),在您的RandomGreetings类中实现它,并使用另一个public方法来创建并返回“可见的包” {{1 }}类。代码可能看起来像这样:

RandomGreetings

这由package org.example; public interface Greeting { public String say(); } 类实现:

RandomGreetings

然后,您定义一个package org.example.greetings; import org.example.Greeting; class RandomGreetings implements Greeting { // ... } 助手类,以从public包中返回一个RandomGreetings对象:

org.example.greetings

使用package org.example.greetings; import org.example.Greeting; public GeneratorHelper { public static Greeting buildIt() { return new RandomGreetings(); } } 方法时,您会得到一些实现GeneratorHelper.buildIt()接口的对象。但是您无法访问Greeting类本身,因为它仍然是“包可见的”。