What's Alternative to Singleton

最后都变了- 提交于 2020-01-08 11:22:08

问题


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.


回答1:


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

  • Using dependency injection to avoid singletons
  • Singletons are Pathological Liars
  • Root Cause of Singletons
  • Where have all the Singletons Gone?

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.




回答2:


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.




回答3:


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

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.

This is the approach I usually take!




回答4:


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().

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




回答5:


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




回答6:


don't accumulate responsibilites to a single configuration object since 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 Configuration object, then recompile all the classes that uses it. This is somewhat problematic.

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

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 framework will help a lot here, but it isn't stricly required.




回答7:


You can accomplish the same behavior of singleton by using static methods. Steve yegge explains it very well in this post.




回答8:


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.




回答9:


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

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




回答10:


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)



回答11:


You could use a dependency injection framework to ease the pain of passing in the configuration object. A decent one is ninject which has the advantage of using code rather than xml.




回答12:


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).




回答13:


Singletons are not evil but the design pattern is flawed. I have a class that I only want to create a single instance of it during runtime but want to create multiple isolated instances during unit testing to ensure deterministic results.

DI using Spring, etc, is a very good option but not the only option.



来源:https://stackoverflow.com/questions/1300655/whats-alternative-to-singleton

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!