概述:我们很多时候需要一个类只产生一个实例。类似双击金山词霸一个金山词霸的进程运行起来了,然后你在双击并没有在运行一个新的进程。运行两个程序除了浪费资源以外没有任何其他作用。另外有时后生成多个对象还会出现意想不到的问题。

单件模式:确保一个类只有一个实例,并提供一个全局访问点。

实现分析:要保证只有一个实例,就不能让客户代码能够 new 出这个类的一个对象来。而应该让这个类本身来管理对象的实例化,如果没有生成对象就生成一个新对象,已经存在就把这个对象 return 出去。
namespace singleton
{
   
public class SingletonClass
    
{
        SingletonClass singletonClass;
        
private SingletonClass()
        
{
        }

        
public static SingletonClass getInstance()
        
{
            
if (singletonClass == null)
            
{
 System.Threading.Thread.Sleep(100);
                singletonClass 
= new SingletonClass();
            }

            
return singletonClass;
        }

    }

}

看看调用代码:
 class Program
    
{
        
static void Main(string[] args)
        
{
            System.Threading.Thread thread 
= new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(ThreadMethod));
            thread.Start();

            
for (int i = 0; i < 100; i++)
            
{
                Console.WriteLine(
"主线程"+SingletonClass.getInstance().GetHashCode());
            }

        
            Console.ReadLine();
        }


        
public static void ThreadMethod(object o)
        
{
            
for (int i = 0; i < 100; i++)
            
{
                Console.WriteLine(
"子线程"+SingletonClass.getInstance().GetHashCode());
            }

        }

    }


运行结果:
......
子线程39086322
子线程39086322
子线程39086322
主线程45653674
主线程39086322
主线程39086322
主线程39086322
主线程39086322
......
从运行结果看多线程情况下会发现产生了两个对象。...看来还有改进的必要。
 public class SingletonClass
    
{
       
static SingletonClass singletonClass   = null;  
       
private static object  obj= new object();
      
        
private SingletonClass()
        
{
        }

        
public static SingletonClass getInstance()
        
{
            
lock (obj)
            
{
                
if (singletonClass == null)
                
{
                    System.Threading.Thread.Sleep(
100);
                    singletonClass 
= new SingletonClass();
                }

            }

            
return singletonClass;
        }

    }

这次没有发现有不同的对象。不过每次调用getInstance()都会加锁,这样好像有点浪费啊。因为事实上执行了一次之后就不会为null了,生成一个对象之后对方法的调用都会加锁然后什么也不做然后解锁这样的代码肯定不太合理。

 public static SingletonClass getInstance()
        
{
            
if (singletonClass == null)
            
{
                
lock (obj)
                
{
                    
if (singletonClass == null)
                    
{
                        //System.Threading.Thread.Sleep(
100);
                        singletonClass 
= new SingletonClass();
                    }

                }

            }

            
return singletonClass;
        }


这样好像代码已经完整了。
另外:1.Head First 中 是这样申明唯一实例变量的 static volatial SingletonClass singletonClass   = null;  volatial 是防止编译器做不必要的优化。保证每次都是从内存中取值而不是是从寄存器中取得副本。从而在另一个线程中对该对象的改变该线程都能获得正确的值。
2 从 运行结果还可以看出一个怪异的地方
子线程39086322
子线程39086322
子线程39086322
主线程45653674
主线程39086322
主线程39086322
主线程39086322
主线程39086322

首先产生了一个对象,然后产生第二个对象。根据我们的逻辑我们使用的对象就是第二个对象了(hashcode 为 45653674)但是从打印的结果看除了一个为第二个对象的hashcode 外,所有的都是第一个对象的hashcode.这个问题先不想了,有时间再补上吧