之前在开发winform程序的时候,经常做这样的控制:每个form同时只能出现一个。方法有很多,通常我都采用这种方式:(通过一个public 的static 字段进行控制)
主窗体menu:单例类只能有一个实例。
单例类必须自己创建自己的唯一实例。 **
单例类必须给所有其它对象提供这一实例。
第二条中提到的,单例类只能自己控制,而不是由使用类的用户来控制单例(用户此时不知道是否单例),所以上述做法,虽然可以工作,但却不属于单件模式。
主窗体menu:
private void subMenu1ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (frm.sign == false)
{
frm f = new frm();
f.MdiParent = this;
frm.sign = true;
f.Show();
}
else
{
MessageBox.Show("该窗体已经存在~");
return;
}
}
{
if (frm.sign == false)
{
frm f = new frm();
f.MdiParent = this;
frm.sign = true;
f.Show();
}
else
{
MessageBox.Show("该窗体已经存在~");
return;
}
}
frm窗体:
public static bool sign = false;
public frm()
{
InitializeComponent();
}
private void frm_FormClosing(object sender, FormClosingEventArgs e)
{
sign = false;
}
public frm()
{
InitializeComponent();
}
private void frm_FormClosing(object sender, FormClosingEventArgs e)
{
sign = false;
}
这种方式可以很好的工作。
在Singleton Pattern,提到这种模式有几个特点:
第二条中提到的,单例类只能自己控制,而不是由使用类的用户来控制单例(用户此时不知道是否单例),所以上述做法,虽然可以工作,但却不属于单件模式。
namespace SingletonDemo2
{
class startMain
{
static void Main()
{
SingleTon instance1 = SingleTon.GetInstance();
SingleTon instance2 = SingleTon.GetInstance();
if (instance1 == instance2)
{
Console.WriteLine("equal");
}
}
}
class SingleTon
{
static SingleTon instance = new SingleTon(); //static:CLR 在类成员第一次被访问初始化static变量
private SingleTon() //private: 保证此类不能被实例化
{
}
public static SingleTon GetInstance()
{
return instance;
}
}
}
{
class startMain
{
static void Main()
{
SingleTon instance1 = SingleTon.GetInstance();
SingleTon instance2 = SingleTon.GetInstance();
if (instance1 == instance2)
{
Console.WriteLine("equal");
}
}
}
class SingleTon
{
static SingleTon instance = new SingleTon(); //static:CLR 在类成员第一次被访问初始化static变量
private SingleTon() //private: 保证此类不能被实例化
{
}
public static SingleTon GetInstance()
{
return instance;
}
}
}
这是singleTon pattern的一般形式。
应用单件模式也可以使上述实例很好的工作:
frm:
public partial class frm : Form
{
static frm f=null;
public static frm GetInstance()
{
if (f == null || f.IsDisposed)
{
f = new frm();
}
return f;
}
private frm()
{
InitializeComponent();
}
}
{
static frm f=null;
public static frm GetInstance()
{
if (f == null || f.IsDisposed)
{
f = new frm();
}
return f;
}
private frm()
{
InitializeComponent();
}
}
主窗体menu中:
private void menuToolStripMenuItem_Click(object sender, EventArgs e)
{
frm f = frm.GetInstance();
f.MdiParent = this;
f.Show();
}
{
frm f = frm.GetInstance();
f.MdiParent = this;
f.Show();
}
注意,多线程的程序中,上述简单写法让然可能造成多个实例,故而需要对线程安全性进行控制。
1.双重锁定:
Code
2.静态初始化:
Code
单件模式的在多线程工作时更加有用。如果多个线程对一个类进行作业,如果各自产生自己的类实例,那结果必然是得不到我们的预期目的。这个时候,使用单件模式,使得不管有多少线程,工作的对象都只能是一个共同的实例,这才是我们想要的结果:(下面的例子引用自TerryLee的blog:多线程计数)
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace SingletonDemo2
{
public class Program
{
static void Main(string[] args)
{
MutilThreadCounter count = new MutilThreadCounter();
count.startMain();
}
}
public class MutilThreadCounter
{
public MutilThreadCounter()
{
}
public void doSomeWork()
{
string results = "";
//获得单一实例
Singleton Counter = Singleton.GetInstance();
for (int i = 0; i < 5; i++)
{
Counter.add();
results +="线程";
results += Thread.CurrentThread.Name.ToString() + "——〉";
results += "当前的计数:";
results += Counter.getNum().ToString();
results += "\n";
Console.WriteLine(results);
/**////清空显示字符串
results = "";
}
}
//多线程作业
public void startMain()
{
Thread thread0 = Thread.CurrentThread;
thread0.Name = "thread0";
Thread thread1 = new Thread(new ThreadStart(doSomeWork));
thread1.Name = "thread1";
Thread thread2 = new Thread(new ThreadStart(doSomeWork));
thread2.Name = "thread2";
Thread thread3 = new Thread(new ThreadStart(doSomeWork));
thread3.Name = "thread3";
thread1.Start();
thread2.Start();
thread3.Start();
doSomeWork();
}
}
//单例类定义
public class Singleton
{
//静态初始化
static Singleton instance=new Singleton();
private int num;
public static Singleton GetInstance()
{
return instance;
}
public void add()
{
num++;
}
public int getNum()
{
return num;
}
private Singleton() //private保证不会被类的用户(类外部)被实例化
{
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace SingletonDemo2
{
public class Program
{
static void Main(string[] args)
{
MutilThreadCounter count = new MutilThreadCounter();
count.startMain();
}
}
public class MutilThreadCounter
{
public MutilThreadCounter()
{
}
public void doSomeWork()
{
string results = "";
//获得单一实例
Singleton Counter = Singleton.GetInstance();
for (int i = 0; i < 5; i++)
{
Counter.add();
results +="线程";
results += Thread.CurrentThread.Name.ToString() + "——〉";
results += "当前的计数:";
results += Counter.getNum().ToString();
results += "\n";
Console.WriteLine(results);
/**////清空显示字符串
results = "";
}
}
//多线程作业
public void startMain()
{
Thread thread0 = Thread.CurrentThread;
thread0.Name = "thread0";
Thread thread1 = new Thread(new ThreadStart(doSomeWork));
thread1.Name = "thread1";
Thread thread2 = new Thread(new ThreadStart(doSomeWork));
thread2.Name = "thread2";
Thread thread3 = new Thread(new ThreadStart(doSomeWork));
thread3.Name = "thread3";
thread1.Start();
thread2.Start();
thread3.Start();
doSomeWork();
}
}
//单例类定义
public class Singleton
{
//静态初始化
static Singleton instance=new Singleton();
private int num;
public static Singleton GetInstance()
{
return instance;
}
public void add()
{
num++;
}
public int getNum()
{
return num;
}
private Singleton() //private保证不会被类的用户(类外部)被实例化
{
}
}
}
以上只是对单例模式的应用做了个简单的总结,有关理论还是要参照大牛们的blog:
http://terrylee.cnblogs.com/archive/2005/12/09/293509.html