【问题标题】:Loading Settings - Best Practices加载设置 - 最佳实践
【发布时间】:2011-04-26 11:06:01
【问题描述】:

我正处于我的第一个实际应用程序中,我正在添加用户设置。我正在使用 Java 并且非常 OO(并试图保持这种方式)所以这是我的想法:

  1. 加载main() 中的所有内容并 将其全部“下线”传递给 所需对象(数组)
  2. 同上,但只是通过 包含数据的对象向下 线
  3. 将每个单独的设置加载为 需要在各个类中。

我了解每种方法的一些基本优缺点(即时间与规模),但我正在寻找一些外部意见,了解他们过去成功使用的做法。

【问题讨论】:

  • 我说这个目标足够狭隘——特别是用户设置等……我们可以等着看是否有人给出了一个规范的答案。可悲的是,CW 可能是正确的,因为有无数不同的方法在使用......
  • 对——我建议使用属性,因为它对于简单的用例来说“更”规范。然而,为了真正的可移植性,commons-config 是它的所在。
  • 在阅读了您的回答后,我很清楚 Preferences 确实是执行此操作的更规范方式 :)
  • 我完全不确定 Glenn 是否在询问实际的实现阅读/写作偏好(例如 Preferences API、Jakarta 的 commons-configuration 等);他问的是一种方法——从他的问题中可以明显看出,他更关心方法和设计,而不是特定的实现。有趣的是,这个问题的大多数答案都与阅读设置的特定实现有关,而不是设计。我们错过了格伦的观点吗?
  • @Isaac 我打算找出人们对传递信息的看法,但事实上我确实发现了一些我不知道的事情。然而,你是对的,大多数人都忽略了我真正的要求。

标签: java oop settings


【解决方案1】:

应该有人支持所谓的 Java 标准,Preferences API...,它是JDK6 的最新化身。 编辑添加,由于作者似乎精通XML,因此更多appropriate than before。我想我相信你也可以使用Properties 来处理 XML juju,如果精神带你的话。

与 SO 相关:Preferences API vs. Apache solutionIs a master preferences class a good idea?

(好吧,这就是我愿意做的所有站立。)

【讨论】:

  • 这正是您想要做的。随喜好而去。如果您对 stock 实现不满意,请用您自己的实现覆盖它。但基础是稳固的。这应该是一个简单的服务。
【解决方案2】:

使用 SettingsManager 类或类似的东西,用于抽象获取所有设置数据。在代码中您需要设置的每个点,您都可以查询 SettingsManager 类 - 类似于:

int timeout = SettingsManager.GetSetting("TimeoutSetting");

然后,您将有关如何获取设置的所有逻辑委托给这个单一的管理器类,您可以根据需要更改/优化其实现。例如,您可以实现 SettingsManager 以从配置文件、数据库或其他一些数据存储中获取设置,定期刷新设置,处理检索昂贵的设置的缓存等。使用这些设置的代码仍然很幸福不知道所有这些实施决策。

为了获得最大的灵活性,您可以使用接口而不是实际的类,并让不同的设置管理器实现该接口:您可以根据需要在某个中心点将它们换入和换出,而根本无需更改底层代码。

在 .NET 中,有一组相当丰富的现有配置类(在 System.Configuration 命名空间中)提供此类功能,而且效果很好。

我不确定 Java 的等价物,但它是一个很好的模式。

【讨论】:

  • 您不能在 Java 中使用字符串索引。你需要一张地图。
  • 好吧,代码示例本质上是伪代码:主要思想是您有一些东西可以集中管理获取设置。无论如何,我将其更改为不使用字符串索引。
  • 在(标准)Java 中,这是 Preferences API:download.oracle.com/javase/6/docs/technotes/guides/preferences/…
【解决方案3】:

由于配置/设置通常加载一次(在启动时;或者可能在程序运行时加载几次。无论如何,我们不是在谈论一个非常频繁/耗时的过程),我更喜欢简单而不是效率。

这排除了选项编号 (3)。配置加载将分散在各处。

我不完全确定您列表中 (1) 和 (2) 之间的区别。 (1) 是否意味着“传递谨慎的参数”和 (2) 是否意味着“传递包含整个配置的对象”?如果是这样,我更喜欢(2)而不是(1)。

这里的经验法则是,您应该让事情简单而集中。在一个地方读取配置的好处是它可以让您更好地控制配置源在某些时候发生变化。

【讨论】:

    【解决方案4】:

    Here is a tutorial on the Properties class。来自 Javadocs (Properties):

    Properties 类代表一个 持久的属性集。这 属性可以保存到流或 从流中加载。每个键及其 属性中的对应值 列表是一个字符串。

    一个属性列表可以包含另一个 属性列表作为其“默认值”;这 搜索第二个属性列表,如果 在 原始属性列表。

    本教程给出了以下典型用法的实例化示例:

        . . .
    // create and load default properties
    Properties defaultProps = new Properties();
    FileInputStream in = new FileInputStream("defaultProperties");
    defaultProps.load(in);
    in.close();
    
    // create application properties with default
    Properties applicationProps = new Properties(defaultProps);
    
    // now load properties from last invocation
    in = new FileInputStream("appProperties");
    applicationProps.load(in);
    in.close();
    . . .
    

    当然,您也可以使用基于文件的存储和 XML 或 YAML 解析器相当直接地构建您自己的系统。祝你好运!

    【讨论】:

    • 基本上这就是我所倾向于的,因为我使用 XML 来存储数据。
    • 您可能还想看看@andersoj 给出的答案,Preferences 类似乎是执行此操作的“新方法”...
    【解决方案5】:

    我们最近开始使用 JSR-330 依赖注入(使用来自 SVN 的 Guice),发现可以读取属性文件(或任何其他映射)并将其绑定到启动代码中模块中的 Guice 中,所以那个

    @Inject @Named("key") String value
    

    string 在调用该特定代码时注入了与键对应的值。这是我见过的解决这个问题的最优雅的方法!

    您不必在代码周围拖拉配置对象或在代码的每个角落散布各种神奇的方法调用来获取值 - 您只需向 Guice 提及您需要它,它就在那里。

    注意:我看过 Guice、Weld(基于 Seam)和 Spring,它们都提供注入,因为我们希望在我们自己的代码中使用 JSR-330,而我目前最喜欢 Guice。我认为原因是 Guice 的绑定是最清晰的,而不是 Weld 所发生的幕后魔法。

    【讨论】:

    • 截至 2017 年,我会向任何希望选择 JSR330 实现的人推荐 Dagger 2。编译时错误报告使这个机制更加健壮
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 2010-10-03
    • 2018-10-04
    • 2011-12-08
    • 2020-01-21
    相关资源
    最近更新 更多