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();
}
}
}
浙公网安备 33010602011771号