简体   繁体   English

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

[英]How to organize code logically into package while preserving encapsulation

This is a conceptual question.这是一个概念性的问题。
I usually organize code in packages logically.我通常按​​逻辑组织包中的代码。 Eg: math operation goes in my.package.math or business logic goes into my.package.business and so on.例如:数学运算进入my.package.math或业务逻辑进入my.package.business等等。

In these days I have a doubt that I want to share about a constraint imposed by the package visibility in java.在这些日子里,我怀疑我想分享 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问候服务.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.正如我向您展示的,这段代码无法编译,因为RandomGreetings类是包可见的,这意味着 GreetingsService 无法实例化它。 This problem can be solved put public in the class RandomGreetings :这个问题可以通过将public放在RandomGreetings类中来解决:

public class GreetingsService {
...
}

But RandomGreetings for me is an implementation that I want to keep encapsulation and not public visible.但是RandomGreetings对我来说是一个实现,我想保持封装而不是公开可见。 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.在这种情况下,世界(任何导入我可能生成的 jar 工件的人)都能够看到并调用该类,这不是我想要的。

Another possible solution is to move GreetingsService at the same level of RandomGreetings, like so:另一种可能的解决方案是将GreetingsService移动到 RandomGreetings 的同一级别,如下所示:

+-- 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.在这种情况下,代码编译成功并且RandomGreetings被封装,但我最终RandomGreetings了另一个问题。
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?我知道在 Java 中没有子包可见性,那么您如何管理这种情况?
How do you would solve the problem of my code above?你将如何解决我上面代码的问题?

When you want to use a package, it must have some entry point, which has to be public .当你想使用一个包时,它必须有一些入口点,必须是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".这意味着你的org.example.greetings包必须有一些东西,那就是public ,可以从“外部”使用/调用。 It doesn't have to be your RandomGreetings class.它不必是您的RandomGreetings类。

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.您可以定义一个接口(在org.example包中),在您的RandomGreetings类中实现它,并使用另一个public方法来创建和返回“包可见”的RandomGreetings类。 The code might look like this:代码可能如下所示:

package org.example;

public interface Greeting {
    public String say();
}

This gets implemented by the RandomGreetings class:这由RandomGreetings类实现:

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:然后你定义一个public帮助类来从org.example.greetings包中返回一个RandomGreetings对象:

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.当您使用GeneratorHelper.buildIt()方法时,您将获得一些实现Greeting接口的对象。 But you cannot access the RandomGreetings class itself because it is still "package visible".但是您不能访问RandomGreetings类本身,因为它仍然是“包可见的”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM