单例设计模式的几种实现方法

本文深入探讨了单例模式的两种主要实现方式:饿汉式和懒汉式。详细讲解了每种方式的不同实现,包括直接实例化、枚举式、静态代码块以及静态内部类等多种方法,对比了它们在效率和线程安全性上的差异。

​​​​​​1,饿汉式

1.1 直接实例化饿汉式

/**
 * 饿汉式:直接创建对象,不存在线程安全问题
 * @author lais
 *
 */
public class EHanSingle {

	//私有化构造器
	private EHanSingle(){}
	
	//私有化静态对象,并直接创建,强调单例时可以用final修饰
	private final static EHanSingle single = new EHanSingle();
	
	//提供外界获取方式
	public static EHanSingle getInstance(){
		return single;
	}
	//测试
	public static void main(String[] args) {
		EHanSingle instance1 = EHanSingle.getInstance();
		EHanSingle instance2 = EHanSingle.getInstance();
		System.out.println(instance1);
		System.out.println(instance2);
	}
}

1.2 枚举式饿汉式

/**
 * 枚举类饿汉式
 * 枚举类型:表示该对象是有限的几个,我们限定为一个,就是单例了
 * @author lais
 *
 */
public enum EHanEnum {
	//实例对象
	INSTANCE;
	
	//测试方法
	public static void main(String[] args) { 
		System.out.println(EHanEnum.INSTANCE);
		System.out.println(EHanEnum.INSTANCE);
	}
}

1.3 静态代码块饿汉式

/**
 * 静态代码块饿汉式:使用与复杂场景
 * @author lais
 *
 */
public class EHanSingle2 {

	//私有化构造器
	private EHanSingle2(){}
	
	//私有化静态对象,并直接创建
	private static final  EHanSingle2 single ;
	
	static {
		//可以在初始化对象之前进行某些初始化操作
		//例如,从外界配置文件中加载某些属性数据等
		single = new EHanSingle2();
	}
	//提供外界获取方式 
	public static EHanSingle2 getInstance(){
		return single;
	}
	//测试
	public static void main(String[] args) {
		EHanSingle2 instance1 = EHanSingle2.getInstance();
		EHanSingle2 instance2 = EHanSingle2.getInstance();
		System.out.println(instance1);
		System.out.println(instance2);
	}
}

2、懒汉式

2.1、  线程不安全的懒汉式

/**
 * 懒汉式:懒汉式存在线程安全问题
 * @author lais
 *
 */
public class LanHanSingle {
	
	private LanHanSingle(){}
	
	private static LanHanSingle single;
	
	public static LanHanSingle getInstance(){
		//可以加些判断要求
		single = new LanHanSingle();
		return single;
	}
}

2.2 线程安全的懒汉式

/**
 * 懒汉式:懒汉式存在线程安全问题
 * @author lais
 *
 */
public class LanHanSingle2 {
	
	private LanHanSingle2(){}
	
	private static LanHanSingle2 single;
	
	public static LanHanSingle2 getInstance(){
		//可以加些判断要求
		if(single == null){
			synchronized (LanHanSingle2.class) {
				if(single == null)
					single = new LanHanSingle2();
			}
		}
		return single;
	}
}

2.3 静态内部类懒汉式

/**
 * 在内部类被加载和初始化时,才创建INSTANCE实例对象
 * 静态内部类不会自动随着外部类的加载和初始化而初始化,它是单独去加载和初始化的
 * 因为是在内部类加载和初始化时,创建的,因此时线程安全的
 * @author lais
 *
 */
public class InnerSingle {

	private InnerSingle(){}
	
	private static class Inner{
		private static final InnerSingle INSTANCE = new InnerSingle();
	}
	
	public static InnerSingle getInstance(){
		return Inner.INSTANCE;
	}
}

3,总结

使用饿汉式时,枚举方式最简单

使用懒汉式时,静态内部类方式最简单

### 单例模式的实现方法 #### Eager Initialization (急切初始化) 在某些情况下,如果程序总是需要实例,或者创建实例的成本不高,则可以选择使用急切初始化的方式。这种方式会在类加载时就创建好唯一的实例对象: ```java public class Singleton { private static final Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } } ``` 这种方法简单明了,在多线程环境中不会出现问题,因为静态变量`instance`只被赋值一次[^2]。 #### Lazy Initialization (懒汉式初始化) 对于资源消耗较大的情况,可以采用延迟加载的方式来实现单例模式。这意味着直到第一次调用获取实例的方法才会真正去创建这个唯一实例。下面是一个简单的例子展示如何通过双重检查锁定来安全地实现在多线程环境下的懒加载单例: ```java public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() {} public static Singleton getInstance() { if (uniqueInstance == null) { synchronized (Singleton.class) { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } } } return uniqueInstance; } } ``` 这里利用了Java中的`volatile`关键字以及同步代码块确保即使是在高并发的情况下也能正确无误地返回同一个实例[^4]。 #### Factory Method Implementation (工厂方法实现) 另一种常见的做法是借助于工厂设计模式来进行单例管理。在这种方案里,通常会有一个专门负责生产特定类型的对象的工厂类,并且该工厂内部维护着所生产的每一个类型对应的单一实例副本。当外界请求某个具体的产品时,它先尝试从缓存池中查找是否存在可用的对象;如果有则直接提供给客户端使用;如果没有的话再新造一个并加入到集合当中保存起来供后续重复利用。 ```java class ProductFactory { private Map<String, Object> products = new HashMap<>(); @SuppressWarnings("unchecked") public <T extends Product> T getProduct(Class<T> clazz) throws Exception { String key = clazz.getName(); if (!products.containsKey(key)) { T product = clazz.getDeclaredConstructor().newInstance(); products.put(key, product); } return (T) products.get(key); } } interface Product {} ``` 此段代码展示了基于泛型和反射机制构建的一个通用产品制造者接口及其部分实现逻辑[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值