您的位置:首页 > 其它

Design Pattern: Singleton

2016-09-25 03:34 399 查看
单例模式主要应用于一些本质只需创建一个对象的类,使用这种模式以限制客户端创建对象进行操作时,不能创建多于一个的对象。

常见的单例类就如:交互窗口设计中某个功能窗口,不能让客户端每次点击一次窗口打开按钮就打开一个新的一模一样的窗口,这属于浪费资源。

那对于如何限制只有一个窗口对象被创建?

1)在主窗口的打开子窗口成员函数增加对子窗口对象的引用是否为null的if判断;

2)在子窗口类的定义当中,增加对自己是否已经创建对象的判断;

但如果采用前者的方案,我们需要在每个能打开子窗口的主窗口中都引用这么一段代码,进行最没有意义的代码复制工作。而且,如果出现了Bug的时候,一改就需要改动多处代码。

采用后者则是最佳方案,毕竟控制自己的对象个数就如计划生育一样,是自己的事情。

那么,定义一个类的时候,如何知道自己创建了多少个对象呢?答案是无法知道的,所以,我们只能通过一些特殊的机制来确保。

机制1:

采用private的构造函数,采用一个公有的static and final数据成员指向唯一的类内构造函数构造的对象。每一次只能通过调用这个静态、final数据成员获取对象。

public class Singleton{

public static final Singleton ins = new Singleton();
private Singleton(){};
}

但这样就在还没用到的时候就创建了对象了,如果一直没用到就会造成浪费。

机制2:采用静态函数工厂的模式:

public class Singleton{
private Singletion{}
private Singleton ins;
public static getInstance(){
if(ins==null || ins.disposed){
ins = new Singleton();
}
return ins;
}
}

为什么要采用disposed?因为很多时候,关掉窗口后再打开是时常发生的。如果只判断是否被实例化,可能关掉窗口就再也打不开了。

机制3:使用枚举Enum类型

public enum Singleton{
ins;

......

}

但上述机制只能在单线程中确保单例模式,遇到了多线程模式,需要添加同步锁确保单例:

public class Singleton{
private Singletion{}
private Singleton ins;
public synchronized static getInstance(){
if(ins==null || ins.disposed){
ins = new Singleton();
}
return ins;
}
}

静态方法加同步锁将会锁住整个类不被其它线程调用。

但为了提高效率,我们可以使用双锁机制:

public class Singleton{
private Singletion{}
private Singleton ins;
if (ins == null || ins.disposed){
public synchronized static getInstance(){
if(ins==null || ins.disposed){
ins = new Singleton();
}
return ins;
}
}
}

就减少了大部分的线程等待同时防止了两个线程一起通过第一个if后,先后创建两个对象。所以在锁内又提供了if。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息