大家好,我是 V 哥。再聊到單例模式,你可能會(huì)說老掉牙的問題有啥值得講的,可能還真有,筆試題上鏡率極高的一道題還在考,你的回答如何能從網(wǎng)絡(luò)上千遍一律的回答中脫穎而出,成為卷王,是不是得來點(diǎn)不一樣的東西呢,這20種單例模式的實(shí)現(xiàn)與變異總結(jié),也許可以讓你有新的發(fā)現(xiàn),收藏起來吧。
單例設(shè)計(jì)模式確保一個(gè)類在整個(gè)系統(tǒng)中只存在一個(gè)實(shí)例,通常用于全局訪問的共享資源,如數(shù)據(jù)庫連接、配置文件讀取、線程池等。以下V 哥總結(jié)的20種不同的實(shí)現(xiàn),來看一下:
final
和static
關(guān)鍵字定義。public class SingletonEager {
private static final SingletonEager instance = new SingletonEager();
private SingletonEager() {}
public static SingletonEager getInstance() {
return instance;
}
}
public class SingletonLazy {
private static SingletonLazy instance;
private SingletonLazy() {}
public static SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
}
sychronized
關(guān)鍵字,確保多線程環(huán)境的安全。public class SingletonLazySync {
private static SingletonLazySync instance;
private SingletonLazySync() {}
public static synchronized SingletonLazySync getInstance() {
if (instance == null) {
instance = new SingletonLazySync();
}
return instance;
}
}
public class SingletonDCL {
private static volatile SingletonDCL instance;
private SingletonDCL() {}
public static SingletonDCL getInstance() {
if (instance == null) {
synchronized (SingletonDCL.class) {
if (instance == null) {
instance = new SingletonDCL();
}
}
}
return instance;
}
}
public class SingletonInnerClass {
private SingletonInnerClass() {}
private static class Holder {
private static final SingletonInnerClass INSTANCE = new SingletonInnerClass();
}
public static SingletonInnerClass getInstance() {
return Holder.INSTANCE;
}
}
public enum SingletonEnum {
INSTANCE;
public void someMethod() {
// some code
}
}
import java.util.HashMap;
import java.util.Map;
public class SingletonContainer {
private static Map<String, Object> instanceMap = new HashMap<>();
private SingletonContainer() {}
public static void registerInstance(String key, Object instance) {
if (!instanceMap.containsKey(key)) {
instanceMap.put(key, instance);
}
}
public static Object getInstance(String key) {
return instanceMap.get(key);
}
}
除了常見的7種實(shí)現(xiàn)方式,還有幾種不同的單例模式變體,適合更復(fù)雜的使用場景:
ThreadLocal
變量保證每個(gè)線程有自己的單例實(shí)例。public class SingletonThreadLocal {
private static final ThreadLocal<SingletonThreadLocal> threadLocalInstance =
ThreadLocal.withInitial(SingletonThreadLocal::new);
private SingletonThreadLocal() {}
public static SingletonThreadLocal getInstance() {
return threadLocalInstance.get();
}
}
java.util.concurrent.atomic.AtomicReference
原子類實(shí)現(xiàn)無鎖單例。import java.util.concurrent.atomic.AtomicReference;
public class SingletonCAS {
private static final AtomicReference<SingletonCAS> INSTANCE = new AtomicReference<>();
private SingletonCAS() {}
public static SingletonCAS getInstance() {
while (true) {
SingletonCAS current = INSTANCE.get();
if (current != null) {
return current;
}
current = new SingletonCAS();
if (INSTANCE.compareAndSet(null, current)) {
return current;
}
}
}
}
Enum
的延遲加載特性與雙重檢查鎖來實(shí)現(xiàn)。Enum
保證單例的序列化安全,結(jié)合DCL提高性能。適合對(duì)高性能和安全性要求極高的場景。public class SingletonEnumDCL {
private SingletonEnumDCL() {}
private enum Holder {
INSTANCE;
private final SingletonEnumDCL instance = new SingletonEnumDCL();
}
public static SingletonEnumDCL getInstance() {
return Holder.INSTANCE.instance;
}
}
HashMap
)集中管理多個(gè)不同類型的單例實(shí)例。import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class SingletonRegistry {
private static final Map<String, Object> registry = new ConcurrentHashMap<>();
private SingletonRegistry() {}
public static void registerSingleton(String key, Object instance) {
registry.putIfAbsent(key, instance);
}
public static Object getSingleton(String key) {
return registry.get(key);
}
}
public class SingletonBillPugh {
private SingletonBillPugh() {}
private static class SingletonHelper {
private static final SingletonBillPugh INSTANCE = new SingletonBillPugh();
}
public static SingletonBillPugh getInstance() {
return SingletonHelper.INSTANCE;
}
}
public class SingletonReflectionProof {
private static final SingletonReflectionProof INSTANCE = new SingletonReflectionProof();
private SingletonReflectionProof() {
if (INSTANCE != null) {
throw new IllegalStateException("Instance already created!");
}
}
public static SingletonReflectionProof getInstance() {
return INSTANCE;
}
}
finalize
方法中釋放資源或做額外處理。public class SingletonResource {
private static final SingletonResource INSTANCE = new SingletonResource();
private SingletonResource() {
// 初始化資源
}
public static SingletonResource getInstance() {
return INSTANCE;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
// 釋放資源
}
}
除了以上列出的常見單例模式實(shí)現(xiàn)方式,還有一些變種實(shí)現(xiàn)和特殊情況的單例設(shè)計(jì)。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SingletonProxy {
private static final MySingletonInterface INSTANCE =
(MySingletonInterface) Proxy.newProxyInstance(
MySingletonInterface.class.getClassLoader(),
new Class[]{MySingletonInterface.class},
new SingletonHandler(new MySingleton())
);
private SingletonProxy() {}
public static MySingletonInterface getInstance() {
return INSTANCE;
}
private static class SingletonHandler implements InvocationHandler {
private final MySingleton instance;
public SingletonHandler(MySingleton instance) {
this.instance = instance;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 可以在這里加入權(quán)限控制、日志等
return method.invoke(instance, args);
}
}
}
interface MySingletonInterface {
void doSomething();
}
class MySingleton implements MySingletonInterface {
@Override
public void doSomething() {
System.out.println("Doing something...");
}
}
import java.util.HashMap;
import java.util.Map;
public class ServiceLocator {
private static final Map<Class<?>, Object> services = new HashMap<>();
private ServiceLocator() {}
public static <T> void registerService(Class<T> serviceClass, T instance) {
services.put(serviceClass, instance);
}
@SuppressWarnings("unchecked")
public static <T> T getService(Class<T> serviceClass) {
return (T) services.get(serviceClass);
}
}
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class SingletonObjectPool {
private static final int POOL_SIZE = 5;
private static final Queue<SingletonObjectPool> pool = new ConcurrentLinkedQueue<>();
static {
for (int i = 0; i < POOL_SIZE; i++) {
pool.add(new SingletonObjectPool());
}
}
private SingletonObjectPool() {}
public static SingletonObjectPool getInstance() {
SingletonObjectPool instance = pool.poll();
if (instance == null) {
instance = new SingletonObjectPool();
}
return instance;
}
public void release() {
pool.offer(this);
}
}
clone
方法,防止克隆破壞單例模式。public class SingletonCloneProof implements Cloneable {
private static final SingletonCloneProof INSTANCE = new SingletonCloneProof();
private SingletonCloneProof() {}
public static SingletonCloneProof getInstance() {
return INSTANCE;
}
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Cannot clone singleton instance");
}
}
public class SingletonTimeBased {
private static SingletonTimeBased instance;
private static long lastCreatedTime = System.currentTimeMillis();
private static final long REFRESH_INTERVAL = 30000; // 30 seconds
private SingletonTimeBased() {}
public static synchronized SingletonTimeBased getInstance() {
if (instance == null || System.currentTimeMillis() - lastCreatedTime > REFRESH_INTERVAL) {
instance = new SingletonTimeBased();
lastCreatedTime = System.currentTimeMillis();
}
return instance;
}
}
WeakReference
包裝單例對(duì)象,允許Java垃圾收集器在內(nèi)存不足時(shí)回收該對(duì)象。import java.lang.ref.WeakReference;
public class SingletonWeakReference {
private static WeakReference<SingletonWeakReference> instanceRef;
private SingletonWeakReference() {}
public static synchronized SingletonWeakReference getInstance() {
SingletonWeakReference instance = (instanceRef == null) ? null : instanceRef.get();
if (instance == null) {
instance = new SingletonWeakReference();
instanceRef = new WeakReference<>(instance);
}
return instance;
}
}
這些變種和擴(kuò)展可以用來應(yīng)對(duì)不同的使用場景,從安全性到性能需求再到資源管理需求。根據(jù)特定需求,可以選擇或定制合適的單例實(shí)現(xiàn)方式。關(guān)注威哥愛編程,編程樂無邊。
更多建議: