最近计划跟着剑指offer的面试题学习一下算法。都是学习。
面试题2: 设计一个类,我们只能生成该类的一个实例。
我们来提供六种方法来实现:(最好的实现在最后)
1 最简单的单例模式,但是只适合在单线程下使用(不好)
package com.no2;
/**
* 简单单例模式(只适合单线程下使用)
*
* @author yushen
*
*/
public class Singleton {
// 单例模式的构造函数是私有的
private Singleton() {
}
// 定义一个静态私有实例
private static Singleton instance;
// 提供给外一个生成实例的接口
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
2 可以在多线程下使用的单例模式,有个名字叫懒汉式单例模式(不咋好)
在创建实例之前加一个同步锁,保证多个线程调用下,不会生成多个实例
线程安全。(调用getInstance()方法就会加锁一次,效率不好)
package com.no2;
/**
* 懒汉式单例模式(多线程下可以使用): 加同步锁
*
* @author yushen
*
*/
public class Singleton2 {
// 私有构造方法
private Singleton2() {
}
// 私有实例
private static Singleton2 instance = null;
// 提供给外部调用生成实例使用的方法
public static synchronized Singleton2 getInstance() {
if (instance == null) {
instance = new Singleton2();
}
return instance;
}
}
3 双重检测加锁,在实例已经创建的情况下,可以省去加锁的步骤,比一次检测效率会高一些
线程安全。
package com.no2;
/**
* 双重检测单例模式
* 加同步锁前判断实例是否存在,如果存在,锁都不用加了
* 可以节约加锁步骤,效率比单纯懒汉式要好一点
*
* @author yushen
*
*/
public class Singleton3 {
// 私有构造函数
private Singleton3() {
}
// 私有实例
private static Singleton3 instance = null;
// 提供给外部调用的生成实例方法
public static Singleton3 getInstance() {
if (instance == null) {
synchronized (instance) {
if (instance == null) {
instance = new Singleton3();
}
}
}
return instance;
}
}
4 饿汉式单例模式
在类加载的时候,就已经创建了一个实例,调用getInstance()方法时直接返回就是,就是有一个常驻内存,也能保证只有一个实例。
线程安全。
package com.no2;
/**
* 饿汉式单例模式
*
* @author yushen
*
*/
public class Singleton4 {
// 私有构造函数
private Singleton4() {
}
// 私有静态实例
private static Singleton4 instance = new Singleton4();
// 提供给外部调用生成实例的方法
public static Singleton4 getInstance() {
return instance;
}
}
5 私有静态类实现单例模式
该私有静态内部类只有在调用getInstance()方法时才会创建
线程安全。
package com.no2;
/**
* 静态内部类式单例模式
*
* @author yushen
*
*/
public class Singleton5 {
// 私有构造方法
private Singleton5() {
}
// 私有静态内部类
private static class Singleton {
private final static Singleton5 instance = new Singleton5();
}
// 提供给外部调用生成实例的方法
public static Singleton5 getInstance() {
return Singleton.instance;
}
}
6 最好的永远在最后-单例模式的最佳实现
枚举类实现单例模式
package com.no2;
/**
* 枚举类实现单例模式
* 线程安全
* 保证只有一个实例
* 保证序列化
* 最重要的是代码简洁
* 最佳实现方式
*
* @author yushen
*
*/
public enum Singleton6 {
INSTANCE;
}
就这样用:
package com.no2;
/**
* @author yushen
*
*/
public enum Singleton6 {
INSTANCE{
public Singleton6 getInstance(){
return Singleton6.INSTANCE;
}
};
public Singleton6 getInstance(){
return null;
}
}
实例化就直接这么调用就行:
Singleton6 singleton = Singleton6.INSTANCE.getInstance();
帅不帅!哈哈