问题
This is a conceptual question.
I usually organize code in packages logically.
E.g.: math operation goes in my.package.math
or business logic goes into my.package.business
and so on.
In these days I have a doubt that I want to share about a constraint imposed by the package visibility in java.
Let me show some code to explain better my case: I have the following package structure:
+-- org.example
+-- greetings
| +-- RandomGreetings
+-- GreetingsService
|
+-- Main
and the following code:
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());
}
}
This code, as I show you, doesn't compile because the class RandomGreetings
is package visible that means that GreetingsService can't instantiate it.
This problem can be solved put public in the class RandomGreetings
:
public class GreetingsService {
...
}
But RandomGreetings
for me is an implementation that I want to keep encapsulation and not public visible.
In this scenario, the world (anyone that import the jar artifact the I may produce) is able to see and call that class and that is not something that I want.
Another possible solution is to move GreetingsService
at the same level of RandomGreetings, like so:
+-- org.example
+-- greetings
| +-- RandomGreetings
| |
| +-- GreetingsService
|
+-- Main
In this case, the code compiles successfully and the RandomGreetings
is encapsulated but I end up with another problem for me.
I not more able to organize that class in the package in a logical order.
In this case, there are a few class so the situation is still manageable but if the number of class increase there will be only a unique big package I think.
I know that in Java there is not subpackage visibility, so how do you manage that situation?
How do you would solve the problem of my code above?
回答1:
When you want to use a package, it must have some entry point, which has to be public
. Otherwise you can throw the package away since it can't be used. This means your org.example.greetings
package must have something, that is public
and can be used/called from "outside". It doesn't have to be your RandomGreetings
class.
You can define an interface (in the org.example
package), implement it in your RandomGreetings
class and use another public
method to create and return the "package visible" RandomGreetings
class. The code might look like this:
package org.example;
public interface Greeting {
public String say();
}
This gets implemented by the RandomGreetings
class:
package org.example.greetings;
import org.example.Greeting;
class RandomGreetings implements Greeting {
// ...
}
Then you define a public
helper class to return a RandomGreetings
object from the org.example.greetings
package:
package org.example.greetings;
import org.example.Greeting;
public GeneratorHelper {
public static Greeting buildIt() {
return new RandomGreetings();
}
}
When you use the GeneratorHelper.buildIt()
method you get some object that implements the Greeting
interface. But you cannot access the RandomGreetings
class itself because it is still "package visible".
来源:https://stackoverflow.com/questions/56200895/how-to-organize-code-logically-into-package-while-preserving-encapsulation