How to organize code logically into package while preserving encapsulation

旧城冷巷雨未停 提交于 2021-02-10 12:23:50

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!