单例设计模式懒汉式设计:
一般来说,单例设计模式两种常用的设计方法就是饿汉式和懒汉式。两者的设计思路是一样的,只不过在实现的过程中有点小区别。具体在下面结合代码讲解。
第一步:定义私有的static成员变量,和饿汉式不同的是,这里只是定义变量,并不直接创建实例对象
第二步:将构造方法私有化,保证只能在内部进行调用
第三步:提供一个public的static方法,供外部访问唯一的实例对象
但是在硬件飞速发展的今天,这么一点点小内存应该不是问题了,所以还是建议使用饿汉式的设计方式,因为上面的那种设计方式存在着线程安全问题,当只有单个线程进行访问的时候是没有问题的,但是当有多个线程并发访问的时候,就会出现线程安全问题:可能会出现多次创建实例对象的情况(后面创建的实例会把前面创建的实例覆盖)。
怎样产生的线程安全问题,在这里先不进行解释,改进的办法如下(用同步方法即可):
因为同步方法每次只能有一个线程进入,所以效率较低,为了提高一点效率,对上面的方法进行优化,如
说明:在以后的使用中建议使用饿汉式,因为式不存在线程安全问题,而且效率也高,至于那一点点 内存空间,在如今的硬件上应该不是问题.不过有时候也要具体问题具体分析.
一般来说,单例设计模式两种常用的设计方法就是饿汉式和懒汉式。两者的设计思路是一样的,只不过在实现的过程中有点小区别。具体在下面结合代码讲解。
第一步:定义私有的static成员变量,和饿汉式不同的是,这里只是定义变量,并不直接创建实例对象
public class Singleton {
private static Singleton single;
}
第二步:将构造方法私有化,保证只能在内部进行调用
public class Singleton {
private static Singleton single;
private Singleton(){}
}
第三步:提供一个public的static方法,供外部访问唯一的实例对象
public class Singleton {
private static Singleton instance;
private Singleton() {}
/**
这个方法并不是直接返回instance,它首先需要判断实例对象是否创建,如果没有创建,则创建,
然后返回instance,如果已经创建,则直接返回instance.
当第一次使用的时候,在内存中是不存在该实例对象的,所以第一次调用getInstance方法的时
候会创建实例对象,然后在以后的使用中都不会进行再次创建,就是使用第一次创建的对象.这
样就保证了对象的唯一性。
*/
public static Singleton getInstance() {
if (null == instance) {
instance = new Singleton();
}
return instance;
}
}
通过以上三步,就完成了单例对象的创建,看起来和饿汉式的设计方式区别并不大,只是一个是在需要使用的时候再进行创建;一个是随着类的加载而创建,在使用之前就已经创建好了对象.当我们在设计单例的时候,如果该实例对象占用的内存较大,而使用它的时候又比较晚,我们通常可以选用懒汉式这种设计方式,这样比较节省内存,因为它不用一开始就占着内存不放,而是在使用它的时候才开始创建.这也就是所谓的懒加载或延迟加载。
但是在硬件飞速发展的今天,这么一点点小内存应该不是问题了,所以还是建议使用饿汉式的设计方式,因为上面的那种设计方式存在着线程安全问题,当只有单个线程进行访问的时候是没有问题的,但是当有多个线程并发访问的时候,就会出现线程安全问题:可能会出现多次创建实例对象的情况(后面创建的实例会把前面创建的实例覆盖)。
怎样产生的线程安全问题,在这里先不进行解释,改进的办法如下(用同步方法即可):
public class Singleton {
private static Singleton instance;
private Singleton() {}
/*
用同步方法就可以保证只有最先的那个线程创建一次实例对象,以后的线程都不会进行创建,
但当用了同步方法之后,效率就会明显降低,因为每次只有一个线程能够访问该方法,只有等
一个线程结束访问之后,下一个线程才能够进行访问.
*/
public static synchronized Singleton getInstance() {
if (null == instance) {
instance = new Singleton();
}
return instance;
}
}
因为同步方法每次只能有一个线程进入,所以效率较低,为了提高一点效率,对上面的方法进行优化,如
下所示(不使用同步方法,改成使用同步代码块):
public class Singleton {
private static Singleton instance;
private Singleton() {}
/*
当将同步方法改成同步代码块之后,效率就会明显的提高,当最先的线程进入同步代码块中
将实例创建好之后,以后的线程就不会再进入同步代码块中,只会进行一次判断(这时候的
实例对象已经创建好了)就直接返回instance.
这样效率相对于上面的那种形式会高很多,但相对于饿汉式还是差一点,因为多了一个判断嘛.
*/
public static Singleton getInstance() {
if (null == instance) {
synchronized (Singleton.class) {
if (null == instance) {
instance = new Singleton();
}
}
}
return instance;
}
}
说明:在以后的使用中建议使用饿汉式,因为式不存在线程安全问题,而且效率也高,至于那一点点 内存空间,在如今的硬件上应该不是问题.不过有时候也要具体问题具体分析.
补充:枚举也可以作为一种单例设计模式.