Don't think you are, know you are

博客园 首页 新随笔 管理


Singleton 是比较常见的设计模式了,它的实现很简单,真正具有挑战的是:你如何使用Singleton?

Singleton的目的: 保证应用只有一个全局唯一的实例,并且提供一个访问它的全局访问点。

Singleton的实现要点如下:
1,私有构造函数防止在外部实例化。
2,保存唯一实例的静态的私有变量。
3,初始化并获得唯一实例的静态方法。

这里有一个问题:能否使用全局变量替代Singleton模式?
如果使用全局变量,我们需要在任何使用这个变量的地方判断这个变量是否已经被创建,或者创建后是否被销毁,而Singleton是自维护的,这些事情不需要我们操心。

简单的实现Singleton代码如下:
 class Singleton
  {
    private static Singleton instance;
     protected Singleton()
    {
    }
    public static Singleton getInstance()
    {
      // Use 'Lazy initialization'
      if (instance == null)
      {
        instance = new Singleton();
      }
      return instance;
    }
  }
}

但这样会有2个明显的问题

1,不是线程安全的,这意味着如果两个线程同时访问Getinstance方法,这两个线程都会检验实力是否是空,结果是为空的话,它们都将创建singleton 的实例。
2,Singleton类存储了应用程序中通用、集中化的状态。如果应用程序关闭了,如何自动的保存Singleton的状态。应用程序启动后,如何恢复先前的状态。

下面我会创建一个可以串行化和线程安全的Singleton来解决这两个问题。

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Runtime.Serialization;

namespace Singleton
{
    public class User
    {
        private static User theInstance;
        private static object aLock = new object();               // for lock use
        private string _name;
        private int _age;
        private User()
        {
            _name = "";
            _age = 0;       
        }
        public string Name
        {
            get { return _name; }
            set { _name=value;}
         }
        public int Age
        {
            get { return _age; }
            set { _age = value; }
       
        }
        public override string ToString()
        {
            return "User:" + Name + "(" + Age + ")";
        }
        public static User Instance
        {
            get
            {
                lock (aLock)                           //  guarantee thread safe
                {
                    if (theInstance == null)
                    {
                        theInstance = new User();                   
                    }
                    return theInstance;
                }
           
            }       
        }
        [Serializable]
        public class SerializationHelper : ISerializable
        {
            const string Name_Label = "name";
            const string Age_Label = "age";

            public SerializationHelper()
            { }

            public void GetObjectData(SerializationInfo info, StreamingContext context)
            {
                User _user;
                _user = User.Instance;
                lock (_user)
                {
                    info.AddValue(Name_Label, _user.Name);
                    info.AddValue(Age_Label, _user.Age);
                }
            }
            public SerializationHelper(SerializationInfo info, StreamingContext context)     // 反串行话的时候会调用这个构造函数
            {
                User _User;
                _User = User.Instance;
                lock (_User)
                {
                    _User.Name = info.GetString(Name_Label);
                    _User.Age = info.GetInt32(Age_Label);
                }
            }
        }
    }
}


下面是测试代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading ;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
 
namespace Singleton


 public class Program
    {
        static void Main(string[] args)
        {
            IFormatter formatter=new BinaryFormatter();
            FileStream stream;
            try
            {
              stream =new FileStream ("userstate",FileMode.Open,FileAccess.Read);
              formatter.Deserialize(stream);
              stream.Close();
              DisplayUserInfo();
            }
            catch(FileNotFoundException e)
            {
              Console.WriteLine("No user configuration found");
                User u;
                u=User.Instance;
                Console.Write("Enter your name");
                u.Name=Console.ReadLine();  
                Console.Write("Enter your age");
                u.Age=int.Parse (Console.ReadLine());

                DisplayUserInfo();
           
                stream=new FileStream("userstate",FileMode.Create,FileAccess.Write);
                formatter.Serialize(stream,new User.SerializationHelper());
   
                stream.Close();               
            }
        }
        public static void DisplayUserInfo()
        {
            User u;
            u = User.Instance;
            Console.WriteLine(u.ToString());
            Console.ReadLine(); 
            
        }
    }  
}



   


posted on 2007-07-22 00:42  炭炭  阅读(230)  评论(2编辑  收藏  举报