“主人偏好”课是一个好主意吗?

我有一个类来管理大型软件项目的用户首选项。 项目中可能需要从持久性存储设置或检索用户首选项的任何类都是调用此类上的静态方法。 这种集中管理允许以编程方式完全擦除首选项 – 如果每个pref都是在接近其使用代码的情况下处理的话,这将是不可能的。

在此过程中,我遇到了集中化设计的另一个含义。 该软件具有公共API。 该API可以在jar中自行提供。 该API中的类可能引用pref管理类。 因此,pref管理器必须进入API jar。

每个首选项可能都有一个默认值。 软件启动时,可能会计算该默认值。 算法取决于偏好,因此倾向于驻留在使用代码附近。 因此,如果pref管理器需要提供默认值,它会调用相关的类。

但是现在pref经理已成为一个“章鱼类”,将各种类型的类吸入到不应该存在的API jar中。 如果没有,那么使用API​​ jar的程序很快会遇到ClassDefexception。 如果确实如此,则API jar现在变得臃肿,因为其他每个类都可能引用其他类。

通常,其他Java程序员是否使用集中式类来管理他们的首选项?

将静态pref管理类作为公共API的一部分分发是否有意义?

该pref经理应该是确定默认值的代码的守护者吗?

恕我直言,我认为你的第一个问题的答案是“是”和“否”。

首选项通常作为集中式类处理,因为类是项目中许多类的“接收器”。 尝试更接近调用代码意味着如果相同的首选项稍后在其他地方有用,则会遇到麻烦。 根据我的经验,尝试将偏好设置为“过于接近”也会导致处理非常不一致。

话虽如此,通常最好使用多个偏好类或“偏好集”,每个偏好类或“偏好集”支持模块或子模块。 如果查看体系结构的主要组件,通常会发现可以对逻辑上的分区组进行逻辑分区。 这减少了每个偏好类中的混乱。 更重要的是,它允许您将来将程序拆分为多个jar子。 现在,“默认值”计算器可以放在模块中,但仍然位于足够全局的区域。

我还建议不要将首选项直接设置为静态方法,而是使用一些类似getInstance()的操作来获取首选项管理的共享实例,然后对其进行操作。 根据您的语义,您可能希望锁定该对象一段时间(例如,当用户在UI中编辑首选项时),如果您有实际对象,这将更容易。

对于您的其他问题,我会说您的公共API应该有一种让用户更改首选项的方法,但前提是您可以很好地记录这些更改的结果。

如果您使用单个API函数来获取“参考管理器”,则可以为用户提供自己的“默认值计算器”。 首选项管理器将首先询问此计算器,然后再使用您默认提供的计算器。

难道你不能以一种非常通用的方式处理偏好吗? 然后,您只需使用首选项管理器来处理持久性。 所以从一个类你只需要说一下偏好管理器PreferenceManager.setPreference(key,value),并不关心它在数据语义方面的节省。

还是我太简单了?

我不是Java Dev,但就整个“章鱼类”而言,你能不能只为jar提供一个接口,并在运行时连接接口和prefs管理器之间的调用,使用应用程序配置文件确定prefs管理器实例化?

像.NET提供者模式的东西?

这样你就可以将你的jar与prefs管理器分离。

您可能希望查看Cocoa的NSUserDefaults类以获得灵感。 它通过具有多层首选项(称为域)来处理您描述的问题。 当您查找键的值(例如“PrintUsingAllCaps”)时,它首先检查用户本地域中的值。 如果在那里找不到它,它可以检查系统范围的域或网络级域,等等。

它检查的绝对最后一个位置称为“注册域”,这基本上是硬编码默认值应该去的地方。 因此,在我的代码中的任何一点,我都可以在注册域中写一个首选项,如果用户没有覆盖它, NSUserDefaults将只提供该值。

因此,在您的情况下,您可以为类提供一种方法,以便在访问(可能)用户定义的值之前为其设置默认值。 首选项类不必知道它所服务的类的任何信息。

正如其他人建议的那样,如果你需要更复杂的东西,你可以设置一个DefaultValueProvider回调对象而不是直值。

我删除了第一个答案,因为我误解了作者的要求。

要真正解决实际问题 – 感觉就像您希望将偏好(以及默认值的计算)与使用它们的代码放在一起是有意义的。

您是否可以通过为每个区域使用首选项容器类来满足这两个要求,该区域遵循该区域的模式,但是让它注册“全局”首选项对象集合?

您的全局集合可以执行诸如迭代每组首选项并将其重置为默认值的操作,但您的首选项本身仍将在本地定义和维护,以便它不会分散到代码的其他部分。

我能看到的唯一问题是,如果您允许首选项对象在实例化时注册自己,那么您可能会尝试“重置为默认值”,而某些首选项尚未实例化。

我想这可以通过让主“首选”类实例化所有其他类来解决,然后任何一段代码都可以通过静态getter从中央首选项中检索它的本地首选项对象。

这似乎与一些记录器的工作原理非常相似。 有一个维护日志级别,输出流等的中央机制,但每个类都有自己的“日志”方法实例并记录到它。

我希望这更符合目标。 哦,我也同意接受的答案,不要让你的所有方法都是静态的,总是使用吸气剂 – 你会很高兴你有一天做的。

JSR-10( java.util.prefs.* )API使用带有Class参数的工厂方法来创建Preferences实例。 这样,API可以将属于同一包的不同类的首选项存储在单个文件中。