实现步骤:
1)构造函数私有
2)对外提供一个公共的静态方法,通过类名调用方法创建对象
常见问题:
1)如何实现单例模式?
2)多线程造成的问题,如何解决?如果在多线程中使用,可能会创建多个对象的,构造函数可能会调用不止一次。
3)为代码加锁会影响效率,如何处理?
private void btn1_Click(object sender, EventArgs e)
{
//弹出窗体2,此时不是单例的
//Form2 f2 = new Form2();
//f2.Show();
//换一种方式,但是会报错,因为关闭from2之后,再次点击按钮form2虽然已经关闭,但是不是null,所以不能访问已经释放的资源。
//Form2 f2 = null;
//if (f2==null)
//{
// f2 = new Form2();
//}
//f2.Show();
//换一种方式,这样是可以的。
//Form2 f2 = null; //如果f2已经释放掉了
//if (f2 == null|| f2.IsDisposed)
//{
// f2 = new Form2();
//}
//f2.Show();
}
单例模式类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _07_单例模式演示
{
class SingleInstance
{
//静态只能访问静态,U所以字段也应该是静态的
//因为私有只能在本类中访问,所以字段应该是public的
public static SingleInstance singleInstance;
private static readonly object syn = new object();
//构造函数私有,所以只能在本类中创建对象
private SingleInstance()
{
Console.WriteLine(".");
}
//对外提供一个公开的方法
//必须是静态的,要不然无法调用
public static SingleInstance GetInstance()
{
if (singleInstance==null)
{
//为这段代码加锁
lock (syn)
{
if (singleInstance == null)
{
singleInstance = new SingleInstance();
}
}
}
return singleInstance;
}
//多线程同时访问此单例对象,还是还造成问题,如何解决呢?
}
}
代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace _07_单例模式演示
{
class Program
{
static void Main(string[] args)
{
//如何让这个窗体只会创建一个对象?
//不能通过构造函数创建对象
//SingleInstance singleInstance = SingleInstance.GetInstance();
//多线程会造成的问题:
for (int i = 0; i < 1000; i++)
{
//使用了委托和lamda表达式
Thread td = new Thread(new ThreadStart(() =>
{
//此时会创建三个SingleInstance对象,会打印三个点
SingleInstance singleInstance = SingleInstance.GetInstance();
}));
td.Start();
}
Console.ReadKey();
//两个线程同时调用GetInstance()这个方法,同时执行到 if (singleInstance == null)
//如何解决多线程并发访问的问题:保证这个方法GetInstance()同一时刻只有一个线程在执行。
//为代码加锁
//但是为代码加锁,会影响代码执行效率。因为一个线程必须等待另一个线程执行完毕后才能执行这个方法
//如何即保证单例又能提高效率呢
}
}
}