单例模式简介及在WinForm编程中的实现方法

时间:2023-02-01 20:46:42

单例模式是在设计模式中经常使用的一种,顾名思义就是实现一个只能创建一个实例对象的类。刚接触面向对象的coder可能比较难理解这种模式有何意义,其实举个例子来讲就比较好理解了:很多人都喜欢打网游,你打开一个登陆器登陆上自己的账号后又想登陆一个别的账号,但是还不想关闭当前这个账号,一般情况下你再打开遍登陆器就可以实现了,此时这些登陆窗口的实现就不是单利模式了。当你登陆游戏后进入你的人物界面,你点击人物属性按钮,之后显示出一个窗口,上面标明你的各种属性(力量、敏捷bulabula),不要关闭这个窗口,当你再点击一下属性按钮的时候,你觉得如果再弹出一个一模一样的属性窗口来是不是很怪呢,明明就是一个东西为什么要出来俩?所以这个时候是不会在弹出来另一个窗口的,这个属性按钮的实现可以理解为就是单例模式。(本人不太了解游戏设计,只是单纯的说明这个问题,如果有不对的地方,就这样吧)。如果你不打游戏理解不了这个例子,就试试打开windows的任务管理器,然后再打开一个,again again and again的打开,是不是只显示一个呢?或者你玩命双击回收站。

言归正传,先说说一般情况下如何实现一个单例。首先,要解决的问题是如何让这个类可以让别人创建对象,但是只能创建一次呢?这就需要在类的构造函数最好就是private,这样可以防止外部的调用,其实public也未尝不可。那么private的构造函数又如何创建实例呢,外部创建是肯定不行的,只能在类内部实现,private的构造函数只能在类内部调用,那么可以实例化的唯一一个对象也必须在类内部,必须是static的,一般情况下都是private。都是private的话,外部要怎么调用呢?所以需要一个public的函数来get这个实例。下面看代码实现:

    class Singleton
{
private static Singleton instance;//私有静态变量
private Singleton()//私有构造器,不能外部new创建对象
{
}
public static Singleton GetInstance()//公共函数实现外部访问单例,可以结合C#中属性的实现来访问instance
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
下面我们验证这段代码实现的是不是单例。
   static void Main(string[] args)        {            Singleton a = Singleton.GetInstance();            Singleton b = Singleton.GetInstance();            if (a == b)            {                Console.WriteLine("实例a=实例b。")            }            Console.ReadKey();        }
得到的结果自然是:实例a=实例b。这只是一个简单的示例,下面结合WinForm来看看如何实现一个单例窗口。首先我们实现一个窗口SinglotenForm。
  public partial class SinglotenForm : Form
{
private static SinglotenForm singleform = null;//同样是定义一个静态私有变量
public static SinglotenForm _singleform//设置一个属性get私有变量singleform
{
get
{
if (singleform == null)
singleform = new SinglotenForm();
return singleform;
}
}
private SinglotenForm()//私有构造器
{
InitializeComponent();
}
}
然后创建一个MainForm并加上一个button,用来实现弹出SingletonForm。加入代码:

        private void button1_Click(object sender, EventArgs e)
{
SinglotenForm._singleform.Show();
SinglotenForm._singleform.BringToFront();
}
运行,玩命点按钮,看看有什么结果。

单例模式简介及在WinForm编程中的实现方法

单例窗口只显示一个,好像已经实现了单例,但是当我们关闭单例窗口,再次点击按钮时,却报出来以下这个错误。

单例模式简介及在WinForm编程中的实现方法

提示说:无法访问已经释放的对象。按理说关闭窗口后,单例对象就被dispose了,再次点击按钮的时候应该会被创建的,为什么没有被创建反而说已经释放了呢。这个问题关键在于下面这句判断结果,singleform并不是null。明明是调用了dispose,为什么不是null呢?这个问题我将在另一篇文章中详细讲,现在你只要知道,你点击窗口右上角的X是dispose掉这个窗口,但是指向窗口的singleform并不是空就好了。

<span style="white-space:pre">		</span>if (singleform == null)//dispose后的窗口指针并不是null
singleform = new SinglotenForm();
那么如何解决这个问题呢,很简单,两个办法,一个是重写dispose函数将singleform强行置空,另一个就是在判断的时候加上

<span style="white-space:pre">		</span>if (singleform == null|| singleform.IsDisposed)
singleform = new SinglotenForm();
此时我们就解决了窗口关闭不能再次打开的这个问题。