设计模式-单例模式

来源:互联网 发布:淘宝搜索关键词优化 编辑:程序博客网 时间:2024/06/05 19:59

单例模式是一个很常见的设计模式,广泛应用于各类应用程序的设计中,今天好好的总结一下关于单例模式的内容。先看一下单例模式的类图:

所谓单例模式,其实就是在为了解决类实例过多而产生负面的影响这个问题,所以单例模式就是要保证在内存中最多只有一个类的实例,并提供一个访问它的全局访问点,下面看一个例子,关于WPF中的单例模式;
需求是:主窗体上有一个工具箱的按钮,点击这个按钮就会出现一个新的工具箱的窗体,要求最多只能出现一个工具箱的窗体,怎么办?

private void Form1_Load(object sender,EventArgs){    this.IsMdiContainer = true;}private void ToolStripMenuItemToolBox_Click(object sender,EventArgs e){    FormToolbox ftb = new FormToolbox();    ftb.MdiParent = this;    ftb.show();}

上述代码中每点击按钮一次就会出现一个工具箱的窗体,这显然是不符合要求的,所以必须得对这段代码进行改进!

private FormToolbox ftb;private void Form1_Load(object sender,EventArgs){    this.IsMdiContainer = true;}private void ToolStripMenuItemToolBox_Click(object sender,EventArgs e){    //先判断对象是否为空,如果为空才进行实例化,而且重要的一点是窗体关闭之后实例并不会变成null,而是会变成Disposed    if(ftb == NULL || ftb.IsDisposed){        FormToolbox ftb = new FormToolbox();        ftb.MdiParent = this;        ftb.show();    }}

但是这样有两点坏处,第一:对象是否实例化是在主窗体中进行判断的,这样显然是不符合逻辑的,合乎情理的做法应该是主窗体中只是通知启动工具箱,至于工具箱窗体是否实例化,这要工具箱自己来判断,其他窗体的责任就只是使用它而已。第二:如果其他的窗体也要调用这个工具箱,那么就得复制一份代码过去,如果要修改代码,那么有太多的地方需要修改,不符合软件的设计原则, 因为复制的代码是最容易导致bug的,所以我们还是要进行改进。

public partial class FormToolbox:Form{    private static FormToolbox ftb = null;//静态实例变量    //将构造方法私有化,这样在类的外部就不能实例化这个类的对象,就不会产生多余的实例    private FormToolbox(){        InitializeComponent();    }    //在类的内部进行实例化,并且对外提供静态方法来访问类的实例,这样可以保证唯一实例    public static FormToolbox GetInstance(){        if(ftb == null || ftb.IsDisposed){            ftb = new FormToolbox();            ftb.MdiParentForm1.ActiveForm;        }        return ftb;    }}

如果是在多线程环境下使用单例模式,那么要注意的一点是一定要给if判断的外面加上锁,防止出现多个线程同时通过了if判断,然后创建了多个类的实例。

public static FormToolbox GetInstance(){    Lock(object){        if(ftb == null || ftb.IsDisposed){            ftb = new FormToolbox();            ftb.MdiParentForm1.ActiveForm;        }        return ftb;    }}

上面这段代码看起来性能并不是很好,因为不管对象是不是为空,都需要lock,这种做法会影响性能,所以需要改良:双重锁定!

public static FormToolbox GetInstance(){    if(ftb == null){        Lock(object){            if(ftb == null || ftb.IsDisposed){                ftb = new FormToolbox();                ftb.MdiParentForm1.ActiveForm;            }            return ftb;        }    }}

上面这种单例模式的处理方式是要在第一次被引用时,才会将自己实例化,这种单例模式的实现方式成为懒汉式!
还有一种实现方式是饿汉式,也就是静态初始化,在静态类的实例变量声明的时候就让其初始化,那么这种方式就会在自己别加载的时候就将自己实例化!一般来说,饿汉式的单例类已经足够满足我们的需求!

0 0