什么时候应该使用单例模式代替静态类?

在决定使用 单身还是使用静态类时,请说明设计注意事项。在这样做的时候,你有点被迫去对比这两者,所以无论你能想到什么样的对比,在展示你的思维过程中都是很有用的!此外,每个面试官都喜欢看到说明性的例子。:)

52515 次浏览

When the single class needs state. Singletons maintain a global state, static classes do not.

For instance, making a helper around a registry class: If you have changable hive (HKey Current User vs. HKEY Local Machine) you could go:

RegistryEditor editor = RegistryEditor.GetInstance();
editor.Hive = LocalMachine

Now any further calls to that singleton will operate on the Local Machine hive. Otherwise, using a static class, you would have to specify that Local Machine hive everytiem, or have a method like ReadSubkeyFromLocalMachine.

I'd argue the only difference is syntax: MySingleton.Current.Whatever() vs MySingleton.Whatever(). The state, as David mentioned, is ultimately "static" in either case.


EDIT: The bury brigade came over from digg ... anyhow, I thought of a case that would require a singleton. Static classes cannot inherit from a base class nor implement an interface (at least in .Net they cannot). So if you require this functionality then you must use a singleton.

If by "static class" you mean a class that has only static variables, then they actually can maintain state. My understanding is the that the only difference would be how you access this thing. For example:

MySingleton().getInstance().doSomething();

versus

MySingleton.doSomething();

The internals of MySingleton will obviously be different between them but, thread-safety issues aside, they will both perform the same with regards to the client code.

Singletons should never be used (unless you consider a class with no mutable state a singleton). "static classes" should have no mutable state, other than perhaps thread-safe caches and the like.

Pretty much any example of a singleton shows how not to do it.

If a singleton is something you can dispose of, to clean up after it, you can consider it when it's a limited resource (ie. only 1 of it) that you don't need all the time, and have some kind of memory or resource cost when it is allocated.

The cleanup code looks more natural when you have a singleton, as opposed to a static class containing static state fields.

The code, however, will look kind of the same either way so if you have more specific reasons for asking, perhaps you should elaborate.

The two can be quite similar, but remember that the true Singleton must itself be instantiated (granted, once) and then served. A PHP database class that returns an instance of mysqli is not really a Singleton (as some people call it), because it is returning an instance of another class, not an instance of the class that has the instance as a static member.

So, if you're writing a new class that you plan to allow only one instance of in your code, you might as well write it as a Singleton. Think of it as writing a plain-jane class and adding to it to facilitate the single-instantiation requirement. If you're using someone else's class that you can't modify (like mysqli), you should be using a static class (even if you fail to prefix its definition with the keyword).

Singletons are more flexible, which can be useful in cases where you want the Instance method to return different concrete subclasses of the Singleton's type based on some context.

Static classes can't be passed around as arguments; instances of a singleton can be. As mentioned in other answers, watch for threading issues with static classes.

rp

A singleton may have a constructor and destructor. Depending on your language, the constructor may be called automatically the first time your singleton is used, or never if your singleton is not used at all. A static class would have no such automatic initialization.

Once a reference to a singleton object is obtained, it can be used just like any other object. The client code may not even need to know its using a singleton if a reference to the singleton is stored earlier on:

Foo foo = Foo.getInstance();
doSomeWork(foo); // doSomeWork wont even know Foo is a singleton

This obviously makes things easier when you choose to ditch the Singleton pattern in favor of a real pattern, like IoC.

Use the singleton pattern when you need to compute something at runtime that you would compute at compile time if you could, like lookup tables.

Think of a singleton like a service. It's an object which provides a specific set of functionality. E.g.

ObjectFactory.getInstance().makeObject();

The object factory is an object which performs a specific service.

By contrast, a class full of static methods is a collection of actions that you might want to perform, organised in a related group (The class). E.g.

StringUtils.reverseString("Hello");
StringUtils.concat("Hello", "World");

The StringUtils example here is a collection of functionality that can be applied anywhere. The singleton factory object is a specific type of object with a clear responsibility that can be created and passed around where required.

One of my favorite discussions about this issue is here (original site down, now linked to Internet Archive Wayback Machine.)

To summarize the flexibility advantages of a Singleton:

  • a Singleton can be easily converted into a factory
  • a Singleton can be easily modified to return different subclasses
  • this can result in a more maintainable application

Static classes are instantiated at runtime. This could be time consuming. Singletons can be instantiated only when needed.

I think a place where Singleton will make more sense than the static class is when you have to construct a pool of costly resources (like database connections). You would not be interested in creating the pool if noone ever uses them (static class will means that you do the costly work when class is loaded).

A static class with a load of static variables is a bit of a hack.

/**
* Grotty static semaphore
**/
public static class Ugly {


private static int count;


public synchronized static void increment(){
count++;
}


public synchronized static void decrement(){
count--;
if( count<0 ) {
count=0;
}
}


public synchronized static boolean isClear(){
return count==0;


}
}

A singleton with an actual instance is better.

/**
* Grotty static semaphore
**/
public static class LessUgly {
private static LessUgly instance;


private int count;


private LessUgly(){
}


public static synchronized getInstance(){
if( instance==null){
instance = new LessUgly();
}
return instance;
}
public synchronized void increment(){
count++;
}


public synchronized void decrement(){
count--;
if( count<0 ) {
count=0;
}
}


public synchronized boolean isClear(){
return count==0;


}
}

The state is in ONLY in the instance.

So the singleton can be modified later to do pooling, thread-local instances etc. And none of the already written code needs to change to get the benefit.

public static class LessUgly {
private static Hashtable<String,LessUgly> session;
private static FIFO<LessUgly> freePool = new FIFO<LessUgly>();
private static final POOL_SIZE=5;
private int count;


private LessUgly(){
}


public static synchronized getInstance(){
if( session==null){
session = new Hashtable<String,LessUgly>(POOL_SIZE);
for( int i=0; i < POOL_SIZE; i++){
LessUgly instance = new LessUgly();
freePool.add( instance)
}
}
LessUgly instance = session.get( Session.getSessionID());
if( instance == null){
instance = freePool.read();
}
if( instance==null){
// TODO search sessions for expired ones. Return spares to the freePool.
//FIXME took too long to write example in blog editor.
}
return instance;
}

It's possible to do something similar with a static class but there will be per-call overhead in the indirect dispatch.

You can get the instance and pass it to a function as an argument. This lets code be directed to the "right" singleton. We know you'll only need one of it... until you don't.

The big benefit is that stateful singletons can be made thread safe, whereas a static class cannot, unless you modify it to be a secret singleton.

  • Singletons can implement interfaces and inherit from other classes.
  • Singletons can be lazy loaded. Only when it is actually needed. That's very handy if the initialisation includes expensive resource loading or database connections.
  • Singletons offer an actual object.
  • Singletons can be extended into a factory. The object management behind the scenes is abstract so it's better maintainable and results in better code.

Singletons should not be used in the same way as static classes. In essense,

MyStaticClass.GetInstance().DoSomething();

is essentially the same as

MyStaticClass.DoSomething();

What you should actually be doing is treating the singleton as just another object. If a service requires an instance of the singleton type, then pass that instance in the constructor:

var svc = new MyComplexServce(MyStaticClass.GetInstance());

The service should not be aware that the object is a singleton, and should treat the object as just an object.

The object can certainly be implemented, as an implementation detail and as an aspect of overall configuration, as a singleton if that makes things easier. But the things that use the object should not have to know whether the object is a singleton or not.

A singleton is also a good idea if you want to force efficient caching of data. for example, I have a class that looks up definitions in an xml document. Since parsing the document can take a while, I set up a cache of definitions (I use SoftReferences to avoid outOfmemeoryErrors). If the desired definition is not in the cache I do the expensive xml parsing. Otherwise I return a copy from the cache. Since having multiple caches would mean I still might have to load the same definition multiple times, I need to have a static cache. I choose to implement this class as a singleton so that I could write the class using only normal (non-static) data members. This allows me to still create an istantiation of the class should I need it for some reason (serialization, unit testing, etc.)

How about "avoid both"? Singletons and static classes:

  • May introduce global state
  • Get tightly coupled to multiple other classes
  • Hide dependencies
  • Can make unit testing classes in isolation difficult

Instead, look into Dependency Injection and Inversion of Control Container libraries. Several of the IoC libraries will handle lifetime management for you.

(As always, there are exceptions, such as static math classes and C# extension methods.)

Singleton pattern is generally used to service instance independent or static data where multiple threads can access data at same time. One example can be state codes.

Singleton is like a service, as already mentioned. Pro is its flexibility. Static, well, you need some static parts in order to implement Singleton.

Singleton has code to take care of instantiation of th actual object, which can be a great help if you run into racing problems. In a static solution you may need to deal with racing problems at multiple code locations.

However, same as Singleton can be constructed with some static variables, you may be able to compare it with 'goto'. It can bevery useful for building other structures, but you really need to know how to use it and should not 'overuse' it. Therefore general recommendation is to stick to Singleton, and use static if you have to.

also check the other post: Why choose a static class over a singleton implementation?

refer this

summary:

a. One easy rule of thumb you can follow is if it doesn’t need to maintain state, you can use a Static class, otherwise you should use a Singleton.

b. use a Singleton is if it is a particularly “heavy” object. If your object is large and takes up a reasonable amount of memory, lot of n/w calls(connection pool) ..etc. To make sure that its not going to be instantiated multiple times. A Singleton class will help prevent such the case ever happening