如何解决Java中没有子包可见性的问题

时间:2019-03-04 11:43:09

标签: java package visibility

当我使用DDD编写新组件时,我尝试在一个包中包含一个 public 类,同时保护我的组件 package的所有协作者

通常效果非常好,因为组件的客户端只能使用一个入口点。所有(内部)协作者都将被隐藏。

请考虑一个示例,在该示例中,客户可以使用我专门制造的Java汽车四处行驶。我不希望客户看到车辆的所有内部零件,因此只有Car类是公开的:

org.automobile
|- Car           <-- only Car is public
|- Engine        <-- all collaborators have default (package-protected) visibility
\- Battery

现在,随着领域的发展,事情通常会变得越来越复杂,所以我想将与他们的合作伙伴一起的类移到子包中,以保持结构的整洁:

org.automobile
|- Car
|- drive.Engine           <-- how to make this only available to Car
|- drive.Spark
|- drive.Belt
|- electric.Battery       <-- and this
\- electric.BatteryCell

我现在想让Engine仅{em> 可以看到BatteryCar,因为我组件的客户端仍然不能使用它们直接上课。

我知道Java中没有“子包”可见性,但是除了使用Java 9模块之外,还有其他轻量级的模式可以实现我想要的功能吗?

1 个答案:

答案 0 :(得分:1)

我会说有2种选择。任何人都可以随意介入,这是一个有趣的问题。

为Java代码使用单个文件而不是程序包

这个想法是,您可以使用一个Java文件来声明Car.java(引擎和电池)可用的类和API。声明隐藏在Car中的概念的类(Spark,Belt,BatteryCell)应为私有和静态的,这样它们就不会与声明类具有隐式链接。

这种方法可以扩展,但需要做更多的工作。从某种程度上讲,它也是有帮助的,它不适用于大型代码库,也不适合将来会扩展到更大的代码库。

 org.automobile
|- Car
|- Engine.java           <-- how to make this only available to Car
|- Engine.java-Spark     <--private static class in File Engine.java
|- Engine.java-Belt      <--private static class in File Engine.java
|- Battery.java               <-- package private class
\- Battery.java - BatteryCell <--private static class in File Battery.java

结合使用抽象修饰符和受保护修饰符以及子包

这个想法是您创建公共的Abstract类,其功能由受保护的方法公开。例如AbstractBattery和AbstractEngine。 然后,您可以创建一些充当“代理”的类,并在Car程序包中使用程序包私有实现扩展抽象类,并覆盖要提供的方法。例如引擎和电池。汽车将可以访问抽象类的重写方法。另一个副作用是,您的AbstractClasses中不能具有最终的API方法。

此方法更适合于大型代码库,旨在隐藏意外使用的功能和抽象。但是,这需要更多的工作。 当然,其他人仍然可以扩展AbstractBattery和AbstractEngine并使用它们。

org.automobile
|- Car
|- Engine      <-- extends AbstractEngine, is package private, overrides methods that Car needs to  access
|- Battery     <-- extends AbstractBattery,is package private, overrides methods that Car needs to access
|- drive.AbstractEngine <-- Public abstract class with no public methods, methods that are needed by Engine and Car are protected.
|- drive.Spark <-package private
|- drive.Belt <-package private
|- electric.AbstractBattery <--Public abstract class with no public methods, methods that are needed by Battery and Car are protected.
\- electric.BatteryCell <-package private

这是一个看起来像这样的例子:

org.automobile.engine.AbstractEngine

package org.automobile.engine;

public abstract class AbstractEngine {

    protected void startEngine(){
        System.out.println("Zoom Zooomm Zoommm");
    }
}

org.automobile.Engine

package org.automobile;

import org.automobile.engine.AbstractEngine;

final  class Engine extends AbstractEngine {

    @Override
    protected void startEngine(){
        super.startEngine();
    }
}