Java 构造客户端REST库的最惯用方法是什么?

Java 构造客户端REST库的最惯用方法是什么?,java,rest,sdk,access-modifiers,idioms,Java,Rest,Sdk,Access Modifiers,Idioms,我正在写一个RESTAPI。我想把我的类分成整洁的小文件夹,但我仍然希望它们彼此都有包访问权限 原因是我只希望一个类具有公共访问权限 例如: +---com.mysuper.sdk | +------ models | |---- Model.java +------ controllers | |---- Controller.java | +---PublicAPI.java java需要能够看到所有的模型和控制器 控制器需要能够看到模型 任何使用我的库

我正在写一个RESTAPI。我想把我的类分成整洁的小文件夹,但我仍然希望它们彼此都有包访问权限

原因是我只希望一个类具有公共访问权限

例如:

+---com.mysuper.sdk
|
+------ models
|          |---- Model.java
+------ controllers
|          |---- Controller.java
|
+---PublicAPI.java
  • java需要能够看到所有的模型和控制器
  • 控制器需要能够看到模型
  • 任何使用我的库的人应该只能看到PublicAPI.java

  • 最惯用的方式是什么?

    表达代码的最惯用方式,即Java约定,是为代码提供三个包:
    com.mysuper.sdk
    com.mysuper.sdk.models
    &
    com.mysuper.sdk.controllers

    话虽如此,Java语言规范(2015年9月)中没有要求包名反映底层文件夹结构的地方。举例如下:

    /src/com/mysuper/sdk/PublicAPI.java

    package com.mysuper.sdk;
    
    // Public class.
    public class PublicAPI {
        // Main method.
        public static void main(String... args) {
            int[] numbers = new int[args.length];
    
            for (int i = 0; i < args.length; i++) {
                numbers[i] = Integer.parseInt(args[i]);
            }
    
            System.out.println(new Controller().translateNumbers(numbers));
        }
    }
    
    package com.mysuper.sdk;
    
    // Package protected class.
    class Controller {
        // Private model.
        private Model model = new Model();
    
        // Package protected method.
        String translateNumbers(int... numbers) {
            String translation = "";
            for (int number : numbers) {
                translation = translation + model.get(number) + " ";
            }
            return translation;
        }
    }
    
    package com.mysuper.sdk;
    
    // Package protected class.
    class Model {
        // Private database.
        private String[] database = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
    
        // Package protected method.
        String get(int number) {
            if (number < 0 || number > 9) {
                throw new NumberFormatException("Number " + number + " is not between 0 and 9.");
            } else {
                return database[number];
            }
        }
    }
    
    /src/com/mysuper/sdk/models/Model.java

    package com.mysuper.sdk;
    
    // Public class.
    public class PublicAPI {
        // Main method.
        public static void main(String... args) {
            int[] numbers = new int[args.length];
    
            for (int i = 0; i < args.length; i++) {
                numbers[i] = Integer.parseInt(args[i]);
            }
    
            System.out.println(new Controller().translateNumbers(numbers));
        }
    }
    
    package com.mysuper.sdk;
    
    // Package protected class.
    class Controller {
        // Private model.
        private Model model = new Model();
    
        // Package protected method.
        String translateNumbers(int... numbers) {
            String translation = "";
            for (int number : numbers) {
                translation = translation + model.get(number) + " ";
            }
            return translation;
        }
    }
    
    package com.mysuper.sdk;
    
    // Package protected class.
    class Model {
        // Private database.
        private String[] database = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
    
        // Package protected method.
        String get(int number) {
            if (number < 0 || number > 9) {
                throw new NumberFormatException("Number " + number + " is not between 0 and 9.");
            } else {
                return database[number];
            }
        }
    }
    
    您应该按照以下方式获得输出:

    zero one two three four five six seven eight nine
    
    所有这些都已经说过了,有几个原因可以解释为什么你应该坚持把你的课程组织成不同的课程包

  • 大多数IDE会将与文件夹结构不相关的包视为致命的编译错误
  • 这是惯例,因为它有助于代码的可读性,引导其他开发人员找到包含您的类的文件夹
  • 它将鼓励您更好地封装代码,以分离代码模块的责任
  • 如果您希望在遵循Java最佳实践的同时获得类似的结果,我建议您遵循Michael Aaron Safyan的建议,并熟悉从公共接口抽象SDK的实现


    如何最好地为您的项目实现上述模式,最好留给另一个问题。

    *我试图将所有文件放在一个包中,并为它们提供除PublicAPI.java之外的所有包访问权限,PublicAPI.java可能是公共的,但这似乎很草率。为什么您只有一个公共类?我认为这并不是构造API的好方法。您应该有各种公共接口(在适当的情况下),然后是包访问的实现类。您可以使用工厂接口来实例化给定公共接口的实现,也可以使用服务提供程序接口来实例化给定公共接口的实现。它是以这种方式提供给我的。这是什么意思?它最初是以这种方式编写的,我继承了它。我认为这样做的原因可能是他们只希望用户必须实例化API对象的一个实例。你能给我举个简单的例子来说明你的意思吗?我很难理解。谢谢,我实现了这个,它很有效。你的答案写得很好,记录在案,很容易理解,很好的工作。我同意你的观点,我应该使用工厂方法模式,但我会同时使用这个黑客解决方案,直到我有时间更好地重构SDK。你帮了我很大的忙。