加载设置 - 最佳实践

18

我正在开发我的第一个真正应用程序,并正在添加用户设置功能。我使用Java编程,并且非常注重面向对象的编程方式,以下是我的想法:

  1. main() 中加载所有内容,然后将其通过“传递给所需对象”的方式传递到下一级(数组)。
  2. 与上述方法相同,但仅传递包含数据的对象到下一级。
  3. 按需要在各个类中单独加载每个设置选项。

我了解每种方法的基本优缺点(例如时间与空间),但我希望得到外部意见,以获得成功过的最佳做法。


1
我认为这个问题的范围已经足够狭窄了——具体来说,用户设置等等……我们可以等待看看是否有人能提供一个权威答案。不幸的是,由于使用了无数种不同的方法,CW可能是正确的选择。 - andersoj
正确 -- 我建议使用属性,因为对于简单的用例来说它更加规范。然而,对于真正的可移植性,commons-config 是最好的选择。 - Joseph Weissman
读完你的回答后,我明白了偏好设置确实是更规范的方法来完成这个任务 :) - Joseph Weissman
1
我并不确定Glenn是否在询问有关读取/写入偏好设置的实际_实现_(例如Preferences API、Jakarta的commons-configuration等);他在询问一种方法——从他的问题中可以看出,他更关心方法和设计而不是特定的实现。有趣的是,这个问题的大多数答案都与读取设置的特定实现有关,而不是设计。我们是否忽略了Glenn的观点? - Isaac
@Isaac,我本来只是想了解人们对信息传递的看法,但实际上我发现了一些我不知道的事情。然而,你是对的,大多数人忽略了我真正想问的问题。 - user372743
5个回答

8

这正是你想要做的。按照个人喜好进行选择。如果你对原始实现不满意,可以用自己的方式覆盖它。但基础是可靠的。这应该是一个简单的服务。 - Will Hartung

6
使用SettingsManager类或类似的东西来抽象获取所有设置数据。在代码中每个需要设置的地方查询SettingsManager类,例如:
int timeout = SettingsManager.GetSetting("TimeoutSetting");

你可以将所有设置获取的逻辑委托给一个单一的管理器类,其实现可以根据需要进行更改/优化。例如,你可以实现SettingsManager从配置文件、数据库或其他数据存储中获取设置,定期刷新设置,处理昂贵的检索设置的缓存等。使用设置的代码对所有这些实现决策毫不知情。
为了最大程度的灵活性,你可以使用接口而不是实际的类,并让不同的设置管理器实现该接口:在某个集中点,你可以随时替换它们,而无需更改基础代码。
在.NET中,有一组相当丰富的现有配置类(在System.Configuration命名空间中)提供了这种功能,它运作得非常好。
我不确定Java的等效物是什么,但这是一个很好的模式。

1
在Java中,您不能使用字符串索引。您需要使用映射。 - Thorbjørn Ravn Andersen
好的,代码示例本质上是伪代码:主要思想是你有一个中央管理获取设置的东西。无论如何,我已经更改它不使用字符串索引。 - mtreit
在(标准)Java中,这是首选项API:http://download.oracle.com/javase/6/docs/technotes/guides/preferences/index.html - user85421

3

这里有一个关于Properties类的教程。从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来存储数据。 - user372743
您可能还想查看@andersoj提供的答案,Preferences类似乎是实现此功能的“新方法”... - Joseph Weissman

3

由于配置/设置通常只会在启动时加载一次(或者在程序运行期间多次加载几次。无论如何,我们不讨论非常频繁/耗时的过程),我更喜欢简单而不是高效。

这排除了选项(3)。配置加载将散布在各个地方。

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

原则是保持简单和集中。在一个地方读取配置的优点是,如果配置源在某些时候发生更改,它将为您提供更好的控制。


1
我们最近开始使用JSR-330依赖注入(使用来自SVN的Guice),发现可以在启动代码中的模块内读取属性文件(或任何其他映射)并将其绑定到Guice中,以便...
@Inject @Named("key") String value

当特定代码被调用时,字符串将注入与键对应的值。这是我见过解决此问题最优雅的方式!

您不必在代码中传递配置对象或在每个角落撒上各种魔法方法调用来获取值 - 您只需告诉Guice您需要它,它就会出现。

注意:我们查看了提供注入的Guice、Weld(基于Seam)和Spring,因为我们想要在自己的代码中使用JSR-330,并且我目前最喜欢Guice。我认为原因是Guice在其绑定方面最清晰,而Weld则在幕后发生了一些神奇的事情。


截至2017年,我建议任何想选择JSR330实现的人使用Dagger 2。编译时错误报告使得这种机制更加健壮。 - Thorbjørn Ravn Andersen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接