Java 什么是单身人士的替代品

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1300655/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 07:59:33  来源:igfitidea点击:

What's Alternative to Singleton

javadesign-patternssingleton

提问by John Mill

We have a class that holds configuration information for the application. It used to be a singleton. After some architectural review, we were told to remove the singleton. We did see some benefits of not using singleton in the unit testing because we can test different configurations all at once.

我们有一个类来保存应用程序的配置信息。它曾经是一个单身人士。经过一些架构,我们被告知要删除单例。我们确实看到了在单元测试中不使用单例的一些好处,因为我们可以一次测试不同的配置。

Without singleton, we have to pass the instance around everywhere in our code. It's getting so messy so we wrote a singleton wrapper. Now we are porting the same code to PHP and .NET, I am wondering if there is a better pattern we can use for the configuration object.

如果没有单例,我们必须在代码中到处传递实例。它变得如此混乱,所以我们写了一个单例包装器。现在我们将相同的代码移植到 PHP 和 .NET,我想知道是否有更好的模式可以用于配置对象。

采纳答案by FrankS

The Google Testing bloghas a series of entries about avoiding Singleton (in order to create testable code). Maybe this can help you:

谷歌测试博客有一系列的关于避免(以创建可测试的代码)辛格尔顿条目。也许这可以帮助你:

The last article explains in detail how to move the creation of new objects into a factory, so you can avoid using singletons. Worth reading for sure.

上一篇文章详细解释了如何将新对象的创建移动到工厂中,从而避免使用单例。值得一读。

In short we move all of the new operators to a factory. We group all of the objects of similar lifetime into a single factory.

简而言之,我们将所有新操作员转移到工厂。我们将生命周期相似的所有对象分组到一个工厂中。

回答by Thomas Owens

Is a class that contains only static methods and fields possible? I'm not sure of exactly what your situation is, but it might be worth looking into.

一个只包含静态方法和字段的类是否可能?我不确定您的情况到底是什么,但可能值得研究。

回答by gbjbaanb

The best way is to use a Factory pattern instead. When you construct a new instance of your class (in the factory) you can insert the 'global' data into the newly constructed object, either as a reference to a single instance (which you store in the factory class) or by copying the relevant data into the new object.

最好的方法是改用工厂模式。当您构造类的新实例(在工厂中)时,您可以将“全局”数据插入到新构造的对象中,作为对单个实例(存储在工厂类中)的引用或通过复制相关数据到新对象中。

All your objects will then contain the data that used to live in the singleton. I don't think there's much of a difference overall, but it can make your code easier to read.

然后,您的所有对象都将包含曾经存在于单例中的数据。我认为总体上没有太大区别,但它可以使您的代码更易于阅读。

回答by gbjbaanb

I might be stating the obvious here, but is there a reason why you can't use a dependency-injection framework such as Springor Guice? (I believe Spring also is available for .NET as well now).

我可能在这里说的很明显,但是有什么理由不能使用依赖注入框架,例如SpringGuice吗?(我相信 Spring 现在也可用于 .NET)。

That way, the framework can hold a single copy of the configuration objects, and your beans (services, DAOs, whatever) don't have to worry about looking it up.

这样,框架可以保存配置对象的单个副本,而您的 bean(服务、DAO 等等)不必担心查找它。

This is the approach I usually take!

这是我通常采取的方法!

回答by Roland Ewald

Maybe not very clean either, but you could maybe pass the information bits you want to have changed to the method that creates the singleton -- instead of using

也许也不是很干净,但是您可以将要更改的信息位传递给创建单例的方法 - 而不是使用

public static Singleton getInstance() {
    if(singleton != null)
        createSingleton();
        return singleton;
    }
}

you could call createSingleton(Information info)directly on application startup (and in the setUp-Methods of the unit tests).

您可以createSingleton(Information info)在应用程序启动时直接调用(以及在单元测试的 setUp-Methods 中)。

回答by CoverosGene

If you use Spring Framework, you can just create a regular bean. By default (or if you explicitly set scope="singleton") only one instance of the bean is created and that instance is returned every time the bean is used in a dependency or retrieved via getBean().

如果您使用Spring Framework,则只需创建一个常规 bean。默认情况下(或者如果您明确设置scope="singleton"),只会创建 bean 的一个实例,并且每次在依赖项中使用 bean 或通过 检索时都会返回该实例getBean()

You get the advantage of the single instance, without the coupling of the Singleton pattern.

您可以获得单个实例的优势,而无需耦合 Singleton 模式。

回答by saret

Depends on what tooling/frameworks etc.. are being used. With dependency injection/ioc tools one can often still get singleton performance/optimizations by having the di/ioc container use singleton behaviour for the class required - (such as a IConfigSettings interface) by only ever creating one instance of the class. This could be still substituted out for testing

取决于正在使用的工具/框架等。使用依赖注入/ioc 工具,通过让 di/ioc 容器对所需的类使用单例行为(例如 IConfigSettings 接口),通常仍然可以获得单例性能/优化,只需创建类的一个实例。这仍然可以代替测试

Alternately one could use a factory to create the class and return the same instance each time you request it - but for testing it could return a stubbed/mocked version

或者,可以使用工厂来创建类并在每次请求时返回相同的实例 - 但为了测试它可以返回一个存根/模拟版本

回答by koen

The alternative is passing in what you need instead of asking an object for things.

另一种方法是传入您需要的东西,而不是向对象索要东西。

回答by Dewfy

Review possibility to make configuration as callback interface. So your configuration sensitive code will look:

查看将配置配置为回调接口的可能性。因此,您的配置敏感代码将如下所示:

MyReuseCode.Configure(IConfiguration)

System-init code will look:

系统初始化代码将如下所示:

Library.init(MyIConfigurationImpl)

回答by dfa

don't accumulate responsibilites to a single configuration objectsince it will ends in a very big object that is both difficult to understand and fragile.

不要将责任累积到单个配置对象上,因为它将以一个既难以理解又脆弱的非常大的对象结束。

For example if you need another parameter to a particular class you change the Configurationobject, then recompile all the classes that uses it. This is somewhat problematic.

例如,如果您需要更改Configuration对象的特定类的另一个参数,然后重新编译使用它的所有类。这有点问题。

Try refactoring your code to avoid a common, global and big Configurationobject. Pass only required parameters to client classes:

尝试重构您的代码以避免使用通用的、全局的和大的Configuration对象。仅将必需的参数传递给客户端类:

class Server {

    int port;

    Server(Configuration config) {
        this.port = config.getServerPort();
    } 

}

should be refactored to:

应该重构为:

 class Server {

    public Server(int port) {
       this.port = port;
    }
 }

a dependency injection frameworkwill help a lot here, but it isn't stricly required.

一个依赖注入框架将有很大的帮助在这里,但它不是stricly要求。