这是使用“默认”Java 访问来隐藏客户端的类和方法的好习惯吗?

tru*_*nka 5 java oop access-modifiers

  • 在类的情况下:

如果我们使用工厂方法,我们将不得不返回创建的实现作为已实现接口的类型。

public class Factory {

  public Product getProduct() {
    return new ProductA();
  }
}
Run Code Online (Sandbox Code Playgroud)
public interface Product {
}
Run Code Online (Sandbox Code Playgroud)
class ProductA implements Product {
}
Run Code Online (Sandbox Code Playgroud)

为了避免客户将返回的 Product 强制转换为 Product{A, B, C... etc.} 的具体实现,我们必须:

  1. 分别打包客户和工厂的代码(比方说com.example.clientcom.example.factory
  2. 声明具有默认(“包”)访问权限的具体实现(对工厂可见,对客户端不可见)

    package com.example.client;
    ...
    public class Client {
      public static void main(String[] args) {
        Product i = new Factory().getProduct();
        ProductA a = (ProductA) i; // the type of ProductA isn't visible.
      }
    }
Run Code Online (Sandbox Code Playgroud)
  • 在方法的情况下:

例如我们需要使用隐藏方法的同一个工厂

public class Factory {

  public Product getProduct() {
    return new ProductA();
  }

  Product[] getCreatedProducts() {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

我在这里看到两个问题:

  • 糟糕的包结构:隐藏的类和方法必须与调用代码在一个包中。
  • 糟糕的代码:不太直观和易懂。将 java 文件替换为另一个包很容易破坏。

jto*_*ron 4

“默认”访问并不能保证任何事情,因为任何流氓程序员都可以在您的包中声明他们的类。另外,无论你的包结构如何,在java中,你几乎总是可以进行“实例”检查,然后向下转换为“实例”类型。因此,如果您的目标是防止任何向下转型,则必须使用关键字private。例如,您可以将Product接口的具体实现声明private staticFactory. 事实上,在 Bloch 的“如何设计一个好的 API”文章中,他提出了一个观点,即您应该“最小化一切的可访问性”。

也就是说,我认为你有点偏执。如果有人沮丧,对你来说真的那么重要吗?您编写的任何代码都可能被滥用,当然,如果您包含一个记录良好的工厂,那么您就已经提供了有关如何正确使用 API 的明确信息。另外,如果您构建一个真正的工厂方法,它接受参数并具有清晰的方法名称,而不是这个Factory不接受参数的玩具示例,那么我认为您会发现您正在广播正在创建的内容的公共相关部分。