浅谈设计模式系列之单例模式(下)

简介: 浅谈设计模式系列之单例模式

4). 枚举单例模式

不仅可以解决线程同步,还可以防止反序列化。枚举单例模式是《Effective Java》中推荐的

package com.bytearch.designPattern.singleton;
/**
 * 内部枚举类单例模式
 */
public class Singleton {
    private Singleton() {
    }
    /**
     * 静态枚举
     */
     enum SingletonEnum {
        INSTANCE;
        private Singleton singleton;
        SingletonEnum() {
            singleton = new Singleton();
        }
        private Singleton getInstance() {
            return singleton;
        }
    }
    public static Singleton getInstance() {
        return SingletonEnum.INSTANCE.getInstance();
    }
    /**
    * 测试
    * @param args
    */
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            new Thread(()-> {
                System.out.println(Singleton.getInstance().hashCode());
            }).start();
        }
    }
}

5). 容器式单例模式

/**
 * 容器式单例模式
 */
public class ContainerSingleton {
    private ContainerSingleton() {
    }
    private static Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
    public static Object getBean(String className) {
        Object singletonObject = singletonObjects.get(className);
        if (singletonObject == null) {
            synchronized (singletonObjects) {
                singletonObject =  singletonObjects.get(className);
                if (singletonObject == null) {
                    try {
                        try {
                            singletonObject = Class.forName(className).newInstance();
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                        singletonObjects.put(className, singletonObject);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return singletonObject;
    }
}

spring框架中使用的就是容器式单例模式。

下面我们看看Spring源码 org/springframework/beans/factory/support/DefaultSingletonBeanRegistry.java

/**
  * Return the (raw) singleton object registered under the given name.
  * <p>Checks already instantiated singletons and also allows for an early
  * reference to a currently created singleton (resolving a circular reference).
  * @param beanName the name of the bean to look for
  * @param allowEarlyReference whether early references should be created or not
  * @return the registered singleton object, or {@code null} if none found
  */
 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  Object singletonObject = this.singletonObjects.get(beanName);
  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
   synchronized (this.singletonObjects) {
    singletonObject = this.earlySingletonObjects.get(beanName);
    if (singletonObject == null && allowEarlyReference) {
     ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
     if (singletonFactory != null) {
      singletonObject = singletonFactory.getObject();
      this.earlySingletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
     }
    }
   }
  }
  return (singletonObject != NULL_OBJECT ? singletonObject : null);
 }

4.总结

  • ·单例模式有很多"变种",以上是总结的几种比较好的实现(也都是线程安全的),有小伙伴就疑问了,这么多该使用哪一种呢? 其实都可以使用,可以看自己爱好,可能工作上用得比较多的是第一种"饿汉式",个人比较推荐"静态内部类-单例模式",
  • ·以上大家很容易 发现 "容器式单例模式 " 也是 "懒汉模式-双重验证" 的变种,实际场景上我们完全可以根据需要适当定制,做到活学活用。

例如我在轻量级socket连接池实现中也使用了“容器式单例模式”。

public class ConnectionPool {
    /**
     * key is ip:port, value is ConnectionManager
     */
    private final static ConcurrentHashMap<String, ConnectionManager> CP = new ConcurrentHashMap<String, ConnectionManager>();
    public static Connection getConnection(InetSocketAddress socketAddress) throws MyException {
        if (socketAddress == null) {
            return null;
        }
        String key = getKey(socketAddress);
        ConnectionManager connectionManager;
        connectionManager = CP.get(key);
        if (connectionManager == null) {
            synchronized (ConnectionPool.class) {
                connectionManager = CP.get(key);
                if (connectionManager == null) {
                    connectionManager = new ConnectionManager(socketAddress);
                    CP.put(key, connectionManager);
                }
            }
        }
        return connectionManager.getConnection();
    }
}

5.支持

如果你觉得这篇内容对你挺有启发,我想请你帮二个小忙:

  1. 点个 [在看/转发],让更多的人也能看到这篇内容 (喜欢不点在看/转发,都是耍流氓 🙂)
  2. 关注公众号 [浅谈架构], 公众号后台回复以下"编号" 或 "关键字",送你全套适合你的学习资料.
    101: Java初级
    102: Java高级进阶
    103: Java面试
相关文章
|
4月前
|
设计模式 缓存 安全
【设计模式】【创建型模式】单例模式(Singleton)
一、入门 什么是单例模式? 单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。它常用于需要全局唯一对象的场景,如配置管理、连接池等。 为什么要单例模式? 节省资源 场景:某些对象创
164 15
|
11月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
90 2
|
5月前
|
设计模式 存储 安全
设计模式-单例模式练习
单例模式是Java设计模式中的重要概念,确保一个类只有一个实例并提供全局访问点。本文详解单例模式的核心思想、实现方式及线程安全问题,包括基础实现(双重检查锁)、懒汉式与饿汉式对比,以及枚举实现的优势。通过代码示例和类图,深入探讨不同场景下的单例应用,如线程安全、防止反射攻击和序列化破坏等,展示枚举实现的简洁与可靠性。
108 0
|
6月前
|
设计模式 安全 Java
设计模式:单例模式
单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供全局访问点。它通过私有化构造函数、自行创建实例和静态方法(如`getInstance()`)实现。适用于数据库连接池、日志管理器等需要全局唯一对象的场景。常见的实现方式包括饿汉式、懒汉式、双重检查锁、静态内部类和枚举。线程安全问题可通过`synchronized`或双重检查锁解决,同时需防止反射和序列化破坏单例。优点是避免资源浪费,缺点是可能增加代码耦合度和测试难度。实际开发中应优先选择枚举或静态内部类,避免滥用单例,并结合依赖注入框架优化使用。
|
7月前
|
设计模式 存储 安全
设计模式2:单例模式
单例模式是一种创建型模式,确保一个类只有一个实例,并提供全局访问点。分为懒汉式和饿汉式: - **懒汉式**:延迟加载,首次调用时创建实例,线程安全通过双重检查锁(double check locking)实现,使用`volatile`防止指令重排序。 - **饿汉式**:类加载时即创建实例,线程安全但可能浪费内存。 示例代码展示了如何使用Java实现这两种模式。
126 4
|
9月前
|
设计模式 存储 前端开发
前端必须掌握的设计模式——单例模式
单例模式是一种简单的创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。适用于窗口对象、登录弹窗等场景,优点包括易于维护、访问和低消耗,但也有安全隐患、可能形成巨石对象及扩展性差等缺点。文中展示了JavaScript和TypeScript的实现方法。
364 13
|
9月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
110 2
|
10月前
|
设计模式 Java 数据库连接
Java编程中的设计模式:单例模式的深度剖析
【10月更文挑战第41天】本文深入探讨了Java中广泛使用的单例设计模式,旨在通过简明扼要的语言和实际示例,帮助读者理解其核心原理和应用。文章将介绍单例模式的重要性、实现方式以及在实际应用中如何优雅地处理多线程问题。
140 4
|
10月前
|
设计模式 安全 Java
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
Kotlin教程笔记(57) - 改良设计模式 - 单例模式
|
10月前
|
设计模式 存储 数据库连接
PHP中的设计模式:单例模式的深入理解与应用
【10月更文挑战第22天】 在软件开发中,设计模式是解决特定问题的通用解决方案。本文将通过通俗易懂的语言和实例,深入探讨PHP中单例模式的概念、实现方法及其在实际开发中的应用,帮助读者更好地理解和运用这一重要的设计模式。
110 1