在Java应用程序中引入[boolean]配置标志/参数的模式/习惯用法是什么?

在Java应用程序中引入[boolean]配置标志/参数的模式/习惯用法是什么?,java,configuration,boolean,configuration-files,Java,Configuration,Boolean,Configuration Files,我有一个Java应用程序(确切地说是一个用antlr4编写的解释器),在代码中有许多选项,我希望是[power]用户可配置的。类似于config.properties文件。大多数都是布尔标志,如果设置了,就这样做,否则就那样做 目前,我每个标志有一个类,这些类分散在代码中,大部分在实现需要它的同一个包中。你可以说: import my.package.DoThis; if (DoThis.isSet()) { doThis(); } else { do

我有一个Java应用程序(确切地说是一个用antlr4编写的解释器),在代码中有许多选项,我希望是[power]用户可配置的。类似于config.properties文件。大多数都是布尔标志,如果设置了,就这样做,否则就那样做

目前,我每个标志有一个类,这些类分散在代码中,大部分在实现需要它的同一个包中。你可以说:

import  my.package.DoThis;

   if (DoThis.isSet()) {
       doThis();
   } else {
       doThat();
   }
DoThis的代码类似于

package my.package;

public class DoThis {

  private static Boolean doThis = true; // the default
  public static Boolean isSet() { return doThis; }
  public static void set() { doThis = true; }
  public static void clear() { doThis = false; }
}
而且,main调用的代码有一个集中的部分,用于初始化这些选项

public void setup() {
   DoThis.set();
   DoAnother.clear();
   if (cmd.option.debug()) { DoThird.set(); } else { DoThird.clear(): }
}
但是,正如我所说的,我希望清理代码并使用一个配置文件,我可以将其保存在资源中,或者超级用户可以覆盖它。属性文件或json文件似乎是正确的用户界面

但是,属性读取字符串时,是否检查是/否、真/假?设置标志。还是有更好的事情要做

我是否应该将所有选项作为一个类的一部分,并将它们存储在地图中?什么使添加配置选项更容易


最重要的是,我希望遵循某种形式的Java最佳实践来实现这一点。我不想成为那种能用任何语言编写FORTRAN的人。我希望代码看起来像其他Java程序员自然编写的代码。我很确定我现在拥有的不是它。

我不知道有一种普遍接受的“最佳”方法来解决这个问题。我的偏好不是每个标志都有一个单独的类,而是将所有标志集中在一个名为
Config
的类中。它的公共API可能类似于以下内容(假设这些标志被称为
x
y
z
):

如果不想将
Config
的实例作为参数传递给应用程序中的许多不同操作/构造函数,那么可以创建
Config
的单例实例


我认为我上面的建议不会在程序员中引起太大争议。更有可能引起争议的是关于初始化
Config
对象的“最佳”方式的意见。有些人可能会建议使用Spring框架来注入从XML文件获得的值。其他一些人可能建议您的
setup()
操作应该以您最喜欢的语法(属性、JSON、XML或其他任何语法)从配置文件中读取值,并可能允许命令行选项覆盖配置文件中指定的值,我也倾向于单一班级。我可以“轻松”制作一个Emacs宏,将我现在拥有的独立类合并/转换为您建议的格式。使用显式变量而不是“映射”作为实现的任何理由。如果我使用映射,就很容易使用现有的序列化/反序列化代码对其进行初始化。私有变量加上访问它的公共get和set操作的组合在Java术语中称为属性,这是一种常用的习惯用法,因此其他程序员会觉得熟悉。除此之外,对
boolean getX()
的调用将在几个时钟周期内执行,而对
bool get(String name)
的调用将需要更多的时钟周期才能执行,如果实现必须查找映射并可能将返回值转换为布尔值。因此,如果经常查询配置值&性能很重要,那么基于属性的方法是好的。使用基于属性的方法的另一个潜在好处是,这是Spring框架的工作原理,但这只有在您考虑使用Spring时才相关。我从来没有使用过基于Java的序列化/反序列化,所以我不知道使用基于属性的方法比使用基于映射的方法更容易还是更难做到这一点。Apache“Properties”类读取一个文件并生成一个映射字符串->字符串。我们至少还有一段代码使用它,读取“环境变量”的设置。因此,我很想遵循它的模式,同时拥有一个映射和一个变量似乎有点过头了,特别是考虑到在读取映射后,需要填充变量,其中大多数变量除了在代码的少数部分之外从未实际使用过,因此,如果代码从未使用该变量,我将支付映射查找的费用来填充该变量。我想如果检索到该值,我可以使用变量来记忆该值。如果我发现某些变量的性能成为问题,我会考虑一下。目前,获得实现正确语义(且可维护)的工作代码比调整性能更重要。
public class Config {
  private boolean x;
  private boolean y;
  private boolean z;
  void setX(boolean value) { x = value; }
  boolean getX() { return x; }
  void setY(boolean value) { y = value; }
  boolean getY() { return y; }
  void setZ(boolean value) { z = value; }
  boolean getZ() { return z; }
}