单例模式(Singleton pattern):单例模式是最常见、最简单的设计模式。它的核心结构只包含了“Singleton类”这一特殊类。使用单例模式可以保证该类只有一个对象而且外部容易访问,从而有效控制了实例对象的个数和资源的使用。如果希望系统中某个类的对象只有一个,最好的方法就是使用单例模式。
单例模式的思路:
1、为了禁止外界对该类实例化,需要把构造方法私有化;
2、为了让该类有对象可用,需要在该类中进行实例化;
3、为了方便外部对该类对象的使用,需要创建一个公共方法来获取该类对象。
单例模式共有两种:饿汉式和懒汉式;饿汉式单例在Singleton类被调用的时候就会实例化一个对象,而懒汉式单例在调用取得对象的方法时才会实例化对象。
饿汉式单例:
public class Singleton
{
private static Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return singleton;
}
}
懒汉式单例:
public class Singleton
{
private static Singleton singleton = null;
private Singleton(){}
public static Singleton getInstance(){
if(singleton == null)
singleton = new Singleton();
return singleton;
}
}
粗略一看,两种单例的代码都没有问题,但细心的读者会发现,懒汉式单例中存在一个比较严重的问题:如果很多个程序同时调用了getInstance()方法,假设有多段代码同时调用该方法,因为此时还没有实例化对象,因此A和B(假设CPU执行完A和B后中断)都进入了if语句中,执行里边的语句,A和B都实例化了。那么,这种情况下,懒汉式单例就不是单例了。
解决办法有两个:一种是在第四行的static和Singleton之间加上一个标示符synchronized。这样,一次就只允许通过一次调用,避免了实例化多个对象的情况。但是,这样做的不好之处就是所花费的时间极大。另一种方法是用双重判断法,代码如下:
public class Singleton
{
private static Singleton singleton = null;
private Singleton(){}
public static Singleton getInstance(){
if(singleton == null)
synchronized (Singleton.class) {
if(singleton == null)
singleton = new Singleton();
}
return singleton;
}
}
我们可以联想到,即使多个代码同时调用getInstance()方法,也只有前几个会进入if并且碰到synchronized锁,这几个中,当第一个实例化后,之后的在第二次判断的时候会退出判断,返回该对象。再后面来的在第一次判断就会跳出,并且返回该对象,这样,对象就一直只有一个了,并且因为只有一次遇到synchronized锁,比起解决办法中的第一种,会省下很多时间。具体的对于单例模式的使用,请读者自行体会。(PS:个人认为饿汉式单例是比较好的一种,因为安全不会出现像懒汉式单例的问题,即使懒汉式单例的问题用第二种解决办法解决了,但是代码也比饿汉式的多很多,因此个人比较推荐使用饿汉式单例,但不一定就只用饿汉式就可以了,具体情况具体判断。)
如果本文有任何错误的地方或者对本文有更好的建议,请评论留言!