C#设计模式-单实例

单例模式就是保证在整个应用程序的生命周期中,在任何时刻,被指定的类只有一个实例,并为客户程序提供一个获取该实例的全局访问点。

1.经典的模式

namespace singleClass
{
    class OnlyOneClass
    {
        private OnlyOneClass() { }
        private static OnlyOneClass instance;
        public static OnlyOneClass getInstance() {
            if (instance == null) {
                    instance = new OnlyOneClass();
                    return instance;
            }
            return instance;
        }
    }
}

分析一下:

1)通过私有化构造函数,使该类被调用的时候不能通过new来实现

2)定义一个静态变量类,它的生命周期和程序的生命周期是一样的,通过该静态变量来保存该类的实例

2)通过一个静态方法来实例化自己,并返还实例化后的结果,因为该方法先检查全局的实例,再判断是否再创建,保证只有一个实例

 

但是,这种方式如果碰到了多线程并发,问题就来了,如A,B两个线程同时访问了这个类,第一次检查时候都是null,会出现两个同时建立自己实例情况,这样就违背单实例模式的原则

 

改进一下后:

2.俗称懒汉模式

namespace singleClass
{
    class OnlyOneClass
    {
        private OnlyOneClass() { }
        public string thisname;
        private static OnlyOneClass instance;
        private static object _lock = new object();
        public static OnlyOneClass getInstance() {
            if (instance == null) {
                lock (_lock)
                {
                    if (instance == null)
                    {
                        instance = new OnlyOneClass();
                        return instance;
                    }
                }
            }
            return instance;
        }
    }
}

解析:

1)声明一个object 变量,作为lock对象

2)先判断instance的变量是否为null,如果不为null也就不用lock了,直接返回实例

3) 如果是null,锁定对象,继续判断是否为null,以防有其他线程在lock前已经新建了实例,lock后可以保证在一个线程内操作

 

3.饿汉模式

class HungerClass{
        private HungerClass() { }
        private readonly static HungerClass instance=new HungerClass ();
        public static HungerClass getInstance(){
            return instance;
        }
    }
可以看出这种模式是在类初始化后就已经实例化了instance,不同于上面的懒汉模式时在调用getInstance()方法后实例化。
这种方式下,线程安全的问题将交给CLR。
 

4.测试

演示一下,通过声明两个OneClass类,只一个对其的thisname赋值,然后输出这两个类的thisname,看看另一个会怎样
class Program
    {
        
        static void Main(string[] args)
        {
            Console.WriteLine("Get a instanc from OnlyOneClass!");
            try {
                OnlyOneClass one = OnlyOneClass.getInstance();//one 第一个类的变量
        
                Console.WriteLine(one.ToString());
                
                  while(true){
                      string ins = Console.ReadLine();
                      if (ins != "") { one.thisname = ins; }//只对one实例的thisname赋值
                      OnlyOneClass two = OnlyOneClass.getInstance();//two 第二个类的变量
                      Console.WriteLine(one.thisname +" one");//输出 one实例的thisname
                      Console.WriteLine(two.thisname +" two"); //输出 two实例的thisname
                      Thread.Sleep(1000);
                  }
            }
            catch (Exception e) {
                Console.WriteLine(e.Message);
            }
           
            Console.ReadKey();
        }
    }
}
image
可以看到这两个实例都来自一个实例。
 
 
posted @ 2014-11-26 09:49  KeithMorning  阅读(746)  评论(1编辑  收藏  举报