Configuration 应用程序配置的单例

Configuration 应用程序配置的单例,configuration,singleton,Configuration,Singleton,到目前为止,在我所有的项目中,我都使用单例模式来访问整个应用程序的应用程序配置。最近我看到很多关于不使用singleton模式的文章,因为这种模式不促进可测试性,也隐藏了组件依赖性。 我的问题是,存储应用程序配置的最佳方式是什么?应用程序配置可以在整个应用程序中轻松访问,而无需在整个应用程序中传递配置对象 提前谢谢 Madhu我认为应用程序配置是对单例模式的一种很好的使用。我倾向于自己使用它,以防止每次访问配置时都必须重新读取配置,因为我希望配置是强类型的(即,不必每次都转换非字符串值)。我通常

到目前为止,在我所有的项目中,我都使用单例模式来访问整个应用程序的应用程序配置。最近我看到很多关于不使用singleton模式的文章,因为这种模式不促进可测试性,也隐藏了组件依赖性。 我的问题是,存储应用程序配置的最佳方式是什么?应用程序配置可以在整个应用程序中轻松访问,而无需在整个应用程序中传递配置对象

提前谢谢


Madhu

我认为应用程序配置是对单例模式的一种很好的使用。我倾向于自己使用它,以防止每次访问配置时都必须重新读取配置,因为我希望配置是强类型的(即,不必每次都转换非字符串值)。我通常在我的单例中构建一些后门方法来支持可测试性——例如,能够注入XML配置以便我可以在测试中设置它,以及能够销毁单例以便在需要时重新创建它。通常,这些是我通过反射访问的私有方法,因此它们对公共接口是隐藏的


编辑我们生活和学习。虽然我认为应用程序配置是少数几个使用单例的地方之一,但我不再这么做了。通常,现在,我将使用配置属性的静态、
Lazy
备份字段创建接口和标准类实现。这使我能够对每个属性进行“一次初始化”行为,并具有更好的可测试性设计。

对于这种特定情况,我将创建一个配置对象,并将其传递给需要它的人

由于它是一种配置,所以它应该只在应用程序的某些部分使用,而不一定是无所不在的

但是,如果您在使用它们时没有遇到问题,并且不想对其进行那么难的测试,那么您应该继续这样做,直到今天

阅读关于为什么它们被认为有害的讨论。我认为大多数问题都是在单身人士拥有大量资源的情况下出现的


对于应用程序配置,我认为保持原样是安全的。

使用依赖项注入将单个配置对象注入到任何需要它的类中。通过这种方式,您可以使用模拟配置进行测试或任何您想要的。。。您并没有明确地得到需要用配置文件初始化的东西。使用依赖项注入,您也不会传递对象。

单例模式似乎是一种方法。这是我写的一个很好的例子。

这里是一个使用

完成的例子。如果任何组件依赖于可以在运行时更改的配置(例如小部件的主题支持),您需要提供一些回调或信号机制来通知更改的配置。这就是为什么在创建时仅将所需参数传递给组件(如颜色)是不够的。 您还需要提供从组件内部对配置的访问(将完整配置传递给组件),或者创建一个组件工厂来存储对配置及其所有创建组件的引用,以便最终应用更改

前者有一个很大的缺点,那就是它会使构造函数变得混乱或破坏接口,尽管它可能是原型制作的最快方法。如果你考虑到“德米特定律”,这是一个很大的否定,因为它违反了封装。 后者的优点是组件保持其特定的接口,组件只获取它们需要的东西,作为一种额外的好处,它为重构提供了一个中心位置(工厂)。从长远来看,代码维护可能会受益于工厂模式


此外,即使工厂是一个单例,它可能会在比配置单例少得多的地方使用。

+1,人们喜欢创建他们的小规则,如“循环只有一个出口”或“不允许单例”。我更喜欢务实而不是教条,因为教条导致人们无法独立思考。如果您只能有一个X对象,那么您应该只有一个XConfig对象。拥有一个配置对象的单一实例是很好的,也是可取的,但是使用单一实例并不能使它变得很好。在实际类中使用测试特定方法之类的hack也不利于干净的代码或测试。您是否有一个带有接口的新“实现”示例,以及一个使用静态的标准类?@tvanfosson如果您在此处添加新示例,效果会更好。所以在这种情况下,配置对象仍然是一个单例,但是代码将使用接口,而不是直接使用类,并且实际的实现将由Spring注入?所以我们可以注入一个模拟对象进行测试。这是正确的吗?@stivlo:对,单个实例将由依赖注入容器(可能是Spring、Guice或其他)管理,代码可能会使用接口,允许您传入一个实现,其中包含要测试的设置。它不一定是一个模拟。。。它可能是真正的实现,只需要你自己添加设置,而不是从文件中读取。因此,@ColinD,请耐心听我说,这里的重点不是Singleton本身不好,它可能是合适的,特别是对于应用程序配置,或者可能是为了维护连接池,但是当依赖项被隐藏时,它会变得很糟糕,所以我们看不到代码依赖项。使用依赖项注入容器设置此依赖项,使其显式。这种结论与“避免单例”的教条有点不同,你同意吗?@stivlo:当我说“单例”时,我指的是应用程序中特定类的单个实例