如何在保留封装的同时将代码逻辑地组织到包中
How to organize code logically into package while preserving encapsulation
这是一道概念题。
我通常在逻辑上组织包中的代码。
例如:数学运算进入 my.package.math
或业务逻辑进入 my.package.business
等等。
最近我怀疑我是否想分享 package visibility in 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());
}
}
正如我向您展示的,此代码无法编译,因为 class RandomGreetings
是包可见的,这意味着 GreetingsService 无法实例化它。
这个问题可以解决把public放在classRandomGreetings
:
public class GreetingsService {
...
}
但是 RandomGreetings
对我来说是一个我想保持封装而不是 public 可见的实现。
在这种情况下,世界(任何导入我可能生成的 jar 工件的人)都能够看到并调用它 class 而这不是我想要的东西。
另一种可能的解决方案是将 GreetingsService
移动到与 RandomGreetings 相同的级别,如下所示:
+-- org.example
+-- greetings
| +-- RandomGreetings
| |
| +-- GreetingsService
|
+-- Main
在这种情况下,代码编译成功并且 RandomGreetings
被封装,但我遇到了另一个问题。
我无法按逻辑顺序组织包中的 class。
在这种情况下,有几个 class 所以情况仍然是可控的,但是如果 class 的数量增加,我认为只有一个独特的大包。
我知道 Java 中没有 subpackage visibility,那么你是如何处理这种情况的?
你会如何解决我上面的代码的问题?
当你想使用一个包时,它必须有一些入口点,它必须是 public
。否则您可以将包裹扔掉,因为它无法使用。这意味着您的 org.example.greetings
包必须包含某些东西,即 public
并且可以是 used/called 来自 "outside"。它不一定是你的 RandomGreetings
class.
您可以定义一个接口(在 org.example
包中),在您的 RandomGreetings
class 中实现它并使用另一个 public
方法创建和 return"package visible"RandomGreetings
class。代码可能如下所示:
package org.example;
public interface Greeting {
public String say();
}
这由 RandomGreetings
class:
实现
package org.example.greetings;
import org.example.Greeting;
class RandomGreetings implements Greeting {
// ...
}
然后定义一个 public
助手 class 到 return 来自 org.example.greetings
包的 RandomGreetings
对象:
package org.example.greetings;
import org.example.Greeting;
public GeneratorHelper {
public static Greeting buildIt() {
return new RandomGreetings();
}
}
当您使用 GeneratorHelper.buildIt()
方法时,您会得到一些实现 Greeting
接口的对象。但是您无法访问 RandomGreetings
class 本身,因为它仍然是 "package visible".
这是一道概念题。
我通常在逻辑上组织包中的代码。
例如:数学运算进入 my.package.math
或业务逻辑进入 my.package.business
等等。
最近我怀疑我是否想分享 package visibility in 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());
}
}
正如我向您展示的,此代码无法编译,因为 class RandomGreetings
是包可见的,这意味着 GreetingsService 无法实例化它。
这个问题可以解决把public放在classRandomGreetings
:
public class GreetingsService {
...
}
但是 RandomGreetings
对我来说是一个我想保持封装而不是 public 可见的实现。
在这种情况下,世界(任何导入我可能生成的 jar 工件的人)都能够看到并调用它 class 而这不是我想要的东西。
另一种可能的解决方案是将 GreetingsService
移动到与 RandomGreetings 相同的级别,如下所示:
+-- org.example
+-- greetings
| +-- RandomGreetings
| |
| +-- GreetingsService
|
+-- Main
在这种情况下,代码编译成功并且 RandomGreetings
被封装,但我遇到了另一个问题。
我无法按逻辑顺序组织包中的 class。
在这种情况下,有几个 class 所以情况仍然是可控的,但是如果 class 的数量增加,我认为只有一个独特的大包。
我知道 Java 中没有 subpackage visibility,那么你是如何处理这种情况的?
你会如何解决我上面的代码的问题?
当你想使用一个包时,它必须有一些入口点,它必须是 public
。否则您可以将包裹扔掉,因为它无法使用。这意味着您的 org.example.greetings
包必须包含某些东西,即 public
并且可以是 used/called 来自 "outside"。它不一定是你的 RandomGreetings
class.
您可以定义一个接口(在 org.example
包中),在您的 RandomGreetings
class 中实现它并使用另一个 public
方法创建和 return"package visible"RandomGreetings
class。代码可能如下所示:
package org.example;
public interface Greeting {
public String say();
}
这由 RandomGreetings
class:
package org.example.greetings;
import org.example.Greeting;
class RandomGreetings implements Greeting {
// ...
}
然后定义一个 public
助手 class 到 return 来自 org.example.greetings
包的 RandomGreetings
对象:
package org.example.greetings;
import org.example.Greeting;
public GeneratorHelper {
public static Greeting buildIt() {
return new RandomGreetings();
}
}
当您使用 GeneratorHelper.buildIt()
方法时,您会得到一些实现 Greeting
接口的对象。但是您无法访问 RandomGreetings
class 本身,因为它仍然是 "package visible".