按键
这真的取决于您的要求。这里有很多选择。对于简单的应用程序,我通常使用将任意配置键映射到值的东西。然后,键的名称可以指定为字符串常量,例如,某处:
public static final String KEY_COLOR = "color";
public static final String KEY_SIZE = "size";
当然,这提出了一个where 来指定这些常量的问题。您可以在某个全局共享位置指定它们(例如,在您的配置类中,或在某些特殊的常量值类中,甚至像您建议的那样作为enum)。这样做的好处是可以让您在一个地方查看所有键名,从而轻松避免冲突。然而,这有一个明显的主要缺点,即破坏了模块化并强制所有类依赖于这个键集合——添加/删除/移动对象现在需要您修改全局键集合。
您可以做的另一件事是将配置键名称定义为实际使用它们的类/包中的字符串常量。这不会破坏模块化。但是,您现在冒着键名与其他不相关的类发生冲突的风险。添加新密钥意味着您必须检查使用您的配置的每个对象,并确保新密钥名称尚未在使用中。
然而,传统的 Java 解决方案是让键名还包括使用它们的类的包(可能还有类名)。例如:
package com.me.whatever;
public class Something {
static final String KEY_COLOR = "com.me.whatever.Something.color";
static final String KEY_SIZE = "com.me.whatever.Something.size";
}
package com.me.util;
public class Other {
static final String KEY_SIZE = "com.me.util.Other.size";
static final String KEY_GROUP = "com.me.util.Other.group";
}
有时只指定包名更有意义,如果这更能代表您的情况。
上述想法也适用于其他配置方案。例如。使用Preferences API,密钥的路径可以从包名中派生出来。该 API 甚至提供了诸如 systemNodeForPackage() 之类的东西来为您解决这个问题。
所以,只要做任何能导致最清晰、最可维护的代码的事情。在简单性、模块化和灵活性之间找到平衡。对于简单的一次性应用程序,只要您所做的事情清楚,打破“OOP”概念并将它们全部放在一个地方并没有错。否则,将键值存储在它们主要使用的位置,并利用包名和类名来确保唯一性并避免键命名空间污染。
请注意,如果键名在多个包之间拆分,enum 不一定是存储键名的最合适或最方便的数据类型。你当然可以想出一些聪明的系统来完成这项工作,但通常字符串常量既足够又易于使用。但是,如果您存储的不仅仅是键(例如值类型),enum 可能是一个合适的解决方案。
值类型
顺便说一下,对于值类型,您也有很多选择。您可以通过客户端类完成转换,而不是在配置端强制执行它——但是,当然,后者在许多情况下非常方便。
使用enum 的问题在于,您实际上是在一个地方定义了所有配置键(见上文),并且在添加或删除类时很难以模块化方式扩展可用的配置键集.
您可以创建一个通用的配置密钥类,可以根据需要进行实例化,而不是使用固定的enum,例如:
public class Conf {
public static class Key {
final String key;
final Class<?> type;
public Key (String key, Class<?> type) {
this.key = key;
this.type = type;
}
}
public Object getValue (Key key) {
...
}
}
通过使用泛型类型可以轻松改进上述内容。
然后在您的客户端类中:
package com.me.whatever;
public class Something {
static final Conf.Key KEY_COLOR = new Conf.Key("com.me.whatever.Something.color", Color.class);
static final Conf.Key KEY_SIZE = new Conf.Key("com.me.whatever.Something.size", Integer.class);
}
再次谈到键名:您甚至可以使包名前缀添加成为Conf.Key 的函数,类似于Preferences.systemNodeForPackage() 的工作方式,方法是将声明类的类型作为参数并提取包名,所以上面的声明变成了,例如:
static final Conf.Key KEY_COLOR = new Conf.Key(Something.class, "color", Color.class);
结论
我掩饰了很多,因为正如我所说,有无限的选择。我不能在这里真正涵盖每个选项的每个案例,但希望您能明白这一点。更多的是以理智的方式接近它,而不是以一种特定的“正确”方式接近它。