您的位置:首页 > 其它

设计模式-单例模式

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



所谓单例模式,其实就是在为了解决类实例过多而产生负面的影响这个问题,所以单例模式就是要保证在内存中最多只有一个类的实例,并提供一个访问它的全局访问点,下面看一个例子,关于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;
}
}
}


上面这种单例模式的处理方式是要在第一次被引用时,才会将自己实例化,这种单例模式的实现方式成为懒汉式!

还有一种实现方式是饿汉式,也就是静态初始化,在静态类的实例变量声明的时候就让其初始化,那么这种方式就会在自己别加载的时候就将自己实例化!一般来说,饿汉式的单例类已经足够满足我们的需求!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: