Reputation: 1263
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.
Upvotes: 126
Views: 59029
Reputation: 4614
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).
Upvotes: 0
Reputation: 2422
The Google Testing blog has 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.
Upvotes: 148
Reputation: 728
You can accomplish the same behavior of singleton by using static methods. Steve yegge explains it very well in this post.
Upvotes: 1
Reputation: 4274
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.
Upvotes: 0
Reputation: 116432
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.
Upvotes: 4
Reputation: 23644
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)
Upvotes: 0
Reputation: 13767
The alternative is passing in what you need instead of asking an object for things.
Upvotes: 4
Reputation: 2227
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
Upvotes: 0
Reputation: 7471
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.
Upvotes: 4
Reputation:
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!
Upvotes: 5
Reputation: 52689
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.
Upvotes: 16
Reputation: 116187
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.
Upvotes: 0