1. 单例模式(Singleton)简介
单例模式:一个类只能生成一个实例,这个实例由该类自己生成。
主要特点:构造函数是 private的,为了禁止外部调用单例类的构造函数,如果在单例类的外部使用去创建( new )单例类的实例会出现编译错误。通常通过单例类的 getInstance() 方法获得单例类的唯一实例,getInstance() 这个方法名不强制、不过通常情况下都是这样命名。
主要解决:解决一个全局使用的类频繁地创建与销毁的问题。例如:MyBatis 中的 SqlSessionFactory 。
2. 单例模式实现
单例模式的实现,有饿汉式、懒汉式。
饿汉式:在类加载时就完成了初始化,所以类加载比较慢,但获取对象的速度快。
懒汉式:在类加载时不初始化,在获取对象时初始化类,类加载比较快,但获取对象的速度快慢。
2.1 饿汉式代码实现
饿汉式代码实现代码如下,加有详细注释。
package Singleton;
/**
* 饿汉式单例模式实现
*/
public class CommonSingleton {
// 私有、静态的 CommonSingleton 对象、 初始化
private static CommonSingleton commonSingleton = new CommonSingleton();
/**
* 私有化构造函数,这样该类不能在外部实例化
* 只能通过 getInstance() 获取 CommonSingleton类 唯一可用的对象
*/
private CommonSingleton() {
System.out.println("生成了一个实例");
}
/**
* 获取 CommonSingleton类 唯一可用的对象
* @return CommonSingleton类 唯一可用的对象
*/
public static CommonSingleton getInstance() {
return commonSingleton;
}
}
测试代码:
package Singleton;
public class Test {
public static void main(String args[]) {
CommonSingleton commonSingleton1 = CommonSingleton.getInstance();
CommonSingleton commonSingleton2 = CommonSingleton.getInstance();
if(commonSingleton1 == commonSingleton2) {
System.out.println("commonSingleton1和commonSingleton2 是同一实例对象");
} else {
System.out.println("commonSingleton1和commonSingleton2 不是同一实例对象");
}
}
}
程序运行截图如下:
2.2 懒汉式(线程不安全 )代码实现
懒汉式(线程不安全 )代码实现如下,加有详细注释。
package Singleton;
/**
* 懒汉单例模式实现
* 懒汉单例模式:在类加载的时候,不创建实例
* 优点:类的加载速度快
* 缺点:获取唯一可用的对象较慢
*/
public class Lazy01Singleton {
// 私有、静态的 CommonSingleton 对象、 未初始化
private static Lazy01Singleton lazy01Singleton;
/**
* 私有化构造函数,这样该类不能在外部实例化
* 只能通过 getInstance() 获取 Lazy01Singleton类 唯一可用的对象
*/
private Lazy01Singleton() {
System.out.println("生成了一个实例");
}
public static Lazy01Singleton getInstance() {
if (lazy01Singleton == null) {
lazy01Singleton = new Lazy01Singleton();
}
return lazy01Singleton;
}
}
测试代码:
package Singleton;
public class Test {
public static void main(String args[]) {
Lazy01Singleton lazy01Singleton01 = Lazy01Singleton.getInstance();
Lazy01Singleton lazy01Singleton02 = Lazy01Singleton.getInstance();
if (lazy01Singleton01 == lazy01Singleton02) {
System.out.println("lazy01Singleton01和lazy01Singleton02 是同一实例对象");
} else {
System.out.println("lazy01Singleton01和lazy01Singleton02 不是同一实例对象");
}
}
}
程序运行结果如下:
2.3 懒汉式(线程安全 )代码实现
懒汉式(线程安全 )代码实现如下,加有详细注释。
package Singleton;
/**
* 线程安全的懒汉单例模式实现
* 懒汉单例模式:在类加载的时候,不创建实例
* 优点:类的加载速度快
* 缺点:获取唯一可用的对象较慢
*/
public class Lazy02Singleton {
// 私有、静态的 CommonSingleton 对象、 未初始化
private static volatile Lazy02Singleton lazy02Singleton;
/**
* 私有化构造函数,这样该类不能在外部实例化
* 只能通过 getInstance() 获取 Lazy01Singleton类 唯一可用的对象
*/
private Lazy02Singleton() {
System.out.println("生成了一个实例");
}
public static Lazy02Singleton getInstance() {
if (lazy02Singleton == null) {
// 对这个类加锁
synchronized (Lazy02Singleton.class) {
if (lazy02Singleton == null) {
lazy02Singleton = new Lazy02Singleton();
}
}
}
return lazy02Singleton;
}
}
测试代码如下:
package Singleton;
public class Test {
public static void main(String args[]) {
Lazy02Singleton lazy02Singleton01 = Lazy02Singleton.getInstance();
Lazy02Singleton lazy02Singleton02 = Lazy02Singleton.getInstance();
if (lazy02Singleton01 == lazy02Singleton02) {
System.out.println("lazy02Singleton01和lazy02Singleton02 是同一实例对象");
} else {
System.out.println("lazy02Singleton01和lazy02Singleton02 不是同一实例对象");
}
}
}
程序运行截图如下:
参考文献:
- 图解设计模式 - 结成浩著、杨文轩译 - 人民邮电出版社