题目:设计一个类,只能生成该类的一个实例
背景:面试中很多公司喜欢问一些设计模式相关问题。常用模式中,Singleton是唯一一个用几十行代码能完整实现的模式。因此,写一个Singleton的类型很常见。
知识:单例模式特点:
- 单例类只能有一个实例
- 单例类必须自己创建自己的唯一实例
- 单例类必须给所有其他对象提供这一实例。
单例模式保证了全局对象的唯一性,避免状态不一致。
线程安全问题:在获取单例的时候,保证不能产生多个实例对象。同时,注意单例对象内的实例变量是会被多线程共享的。单例模式实现方法有5种。
- 饿汉式单例(立即加载方式):在类加载初始化时就创建好一个静态的对象供外部使用,此对象不会改变,本身是线程安全的。Singleton通过将构造方法限定为private避免类在外部被实例化。Singleton的唯一实例只能通过getInstance()方法访问(此处不考虑java反射机制)
- 懒汉式单例(延迟加载方式):多线程环境下会产生多个single对象,可以使用synchronized同步锁(可以解决多个实例对象问题,但效率低下,下一个线程必须等待上一个线程释放锁后,才可以继续运行);使用双重检查,可以避免整个方法被锁,对需要锁的部分加锁,提高执行效率。
- 静态内部类实现:保证了单例在多线程并发下的线程安全性,但遇到序列化对象时,默认运行结果是多例的。
- 静态代码块实现
- 内部枚举类实现
/**
* 第2题:单例设计模式
* 设计一个类,只能生成该类的一个实例
*
* @author jay
* @version 1.0
*/
public class Test2_Singleton {
public static void main(String[] args) {
Singleton6 singleton1 = Singleton6.getInstance();
Singleton6 singleton11 = Singleton6.getInstance();
System.out.println(singleton1.equals(singleton11));
}
}
//饿汉式单例
class Singleton1 {
//私有构造
private Singleton1(){}
private static Singleton1 singleton1 = new Singleton1();
//静态工厂方法
public static Singleton1 getInstance() {
return singleton1;
}
}
//懒汉式单例:非线程安全
class Singleton2 {
//私有构造
private Singleton2(){}
private static Singleton2 singleton2 = null;
public static Singleton2 getInstance() {
if(singleton2 == null) {
singleton2 = new Singleton2();
}
return singleton2;
}
}
//懒汉式单例:线程安全(方法加锁)
class Singleton3 {
private Singleton3(){} //私有构造
private static Singleton3 singleton3 = null;
public static Singleton3 getInstance() {
//等同于 public synchronized static Singleton3 getInstance()
synchronized (Singleton3.class) {
//此处判断,保证线程安全问题
if(singleton3 == null) {
singleton3 = new Singleton3();
}
}
return singleton3;
}
}
//懒汉式单例:线程安全(双重检查锁),提高效率
class Singleton4 {
private Singleton4(){} //私有构造
private static Singleton4 singleton4 = null;
public static Singleton4 getInstance() {
if(singleton4 == null) {//双重检查
synchronized (Singleton4.class) {
if (singleton4 == null) {
singleton4 = new Singleton4();
}
}
}
return singleton4;
}
}
//静态内部类
class Singleton5 {
private Singleton5(){} //私有构造
//静态内部类
private static class InnerClass {
private static Singleton5 singleton5 = new Singleton5();
}
public static Singleton5 getInstance() {
return InnerClass.singleton5;
}
}
// 静态代码块实现
class Singleton6 {
private Singleton6(){} //私有构造
private static Singleton6 singleton6 = null;
//静态代码块
static {
singleton6 = new Singleton6();
}
public static Singleton6 getInstance() {
return singleton6;
}
}
//内部枚举类实现
class SingletonFactory {
//内部枚举类
private enum EnumSingleton{
Singleton;
private Singleton7 singleton7;
//枚举类的构造方法在类加载就是被实例化
private EnumSingleton(){
singleton7 = new Singleton7();
}
public Singleton7 getInstance() {
return singleton7;
}
}
public static Singleton7 getInstance() {
return EnumSingleton.Singleton.getInstance();
}
}
class Singleton7{
public Singleton7(){}
}