这篇比较好理解,就是说让类的对象实例只产生一个。
例如,老婆这个类Wife,你只能有一个实例。
在写程序时,我们可以让程序员只写一次new Wife(),这样可以只产生一个wife。
但是有些程序员不按照这个规定进行,那么我就要用机制来保障你只能有一个wife。
上代码,看看这个wife类是如何构成的。
public class Wife
{
private string name;
private static Wife wife = new Wife();
private Wife()
{
//不允许私自构造一个老婆
}
public static Wife getWife()
{
return wife;
}
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
}
只所以我们用private的构造函数,是因为不能用new去构造一个wife。
而必须用getWife()去得到一个wife。
那我们现在来测试一下,你是不是真的只能有一个老婆。
Wife wife1 = Wife.getWife();
wife1.Name = "张mm";
Wife wife2 = Wife.getWife();
wife2.Name = "王mm";
Console.WriteLine("老婆1: {0}", wife1.Name);
Console.WriteLine("老婆2: {0}", wife2.Name);
输出是:
老婆1:王mm
老婆2:王mm
奇怪,张mm哪里去了?
我们再用ReferenceEquals(object objA, object objB)这个函数来看看两个老婆一不一样
ReferenceEquals的作用是:
如果 objA 是与 objB 相同的实例,或者如果二者都为空引用,则为 ture;否则为 false。
if (object.ReferenceEquals(wife1, wife2))
{
Console.WriteLine("两个老婆是一样的");
}
else
{
Console.WriteLine("两个老婆不是一样的");
}
输出:
两个老婆是一样的
我们在声明wife2时,实际上是返回的wife1,所以这样我们就实现了单体的模式。
还有一种写法:
public class Wife
{
private string name;
private static Wife wife = null;
private Wife(){
//不允许私自构造一个老婆
}
public static Wife getWife()
{
if (wife == null)
{
wife = new Wife();
}
return wife;
}
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
}
我们也可以看见在很多书上也是这么写的。实际上严格的说这个并不能算作是一个单体模式。
之所以这样说,这个和多线程结构有关系。
好我们用多线程来测试一下:
Main()
{
System.Threading.Thread thread1 = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(getYourWife));
System.Threading.Thread thread2 = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(getYourWife));
thread1.Start("张mm");
thread2.Start("王mm");
}
private static void getYourWife(object name)
{
Wife wife = Wife.getWife();
wife.Name = (string)name;
Console.WriteLine(wife.Name);
}
输出是:
张mm
王mm
恭喜你,你用这个漏洞得到了两个老婆。
那如何改进呢?
我们这个时候就要用到静态构造函数了,静态构造函数是在装载类的时候就执行。
public Class Wife
{
static Wife()
{
//不允许私自构造一个老婆
wife = new Wife();
}
private string name;
private static Wife wife = null;
public static Wife getWife()
{
return wife;
}
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}
}