首页 > 其他分享 >单例Singleton

单例Singleton

时间:2023-08-21 14:35:14浏览次数:31  
标签:Singleton return 对象 param clazz params 单例

单例Singleton

单例模式,bean统一管理,但没必要那么重,需要引入框架

1.hutool工具类中提供了单例的管理工具类Singleton

底层:内部通过线程安全的map存储bean对象,每次获取的时候从池子里取出来

2.底层代码

package cn.hutool.core.lang;

import cn.hutool.core.lang.func.Func0;
import cn.hutool.core.map.SafeConcurrentHashMap;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;

import java.util.Set;
import java.util.stream.Collectors;

/**
 * 单例类<br>
 * 提供单例对象的统一管理,当调用get方法时,如果对象池中存在此对象,返回此对象,否则创建新对象返回<br>
 *
 * @author loolly
 */
public final class Singleton {

	private static final SafeConcurrentHashMap<String, Object> POOL = new SafeConcurrentHashMap<>();

	private Singleton() {
	}

	/**
	 * 获得指定类的单例对象<br>
	 * 对象存在于池中返回,否则创建,每次调用此方法获得的对象为同一个对象<br>
	 * 注意:单例针对的是类和参数,也就是说只有类、参数一致才会返回同一个对象
	 *
	 * @param <T>    单例对象类型
	 * @param clazz  类
	 * @param params 构造方法参数
	 * @return 单例对象
	 */
	public static <T> T get(Class<T> clazz, Object... params) {
		Assert.notNull(clazz, "Class must be not null !");
		final String key = buildKey(clazz.getName(), params);
		return get(key, () -> ReflectUtil.newInstance(clazz, params));
	}

	/**
	 * 获得指定类的单例对象<br>
	 * 对象存在于池中返回,否则创建,每次调用此方法获得的对象为同一个对象<br>
	 * 注意:单例针对的是类和参数,也就是说只有类、参数一致才会返回同一个对象
	 *
	 * @param <T>      单例对象类型
	 * @param key      自定义键
	 * @param supplier 单例对象的创建函数
	 * @return 单例对象
	 * @since 5.3.3
	 */
	@SuppressWarnings("unchecked")
	public static <T> T get(String key, Func0<T> supplier) {
		return (T) POOL.computeIfAbsent(key, (k)-> supplier.callWithRuntimeException());
	}

	/**
	 * 获得指定类的单例对象<br>
	 * 对象存在于池中返回,否则创建,每次调用此方法获得的对象为同一个对象<br>
	 *
	 * @param <T>       单例对象类型
	 * @param className 类名
	 * @param params    构造参数
	 * @return 单例对象
	 */
	public static <T> T get(String className, Object... params) {
		Assert.notBlank(className, "Class name must be not blank !");
		final Class<T> clazz = ClassUtil.loadClass(className);
		return get(clazz, params);
	}

	/**
	 * 将已有对象放入单例中,其Class做为键
	 *
	 * @param obj 对象
	 * @since 4.0.7
	 */
	public static void put(Object obj) {
		Assert.notNull(obj, "Bean object must be not null !");
		put(obj.getClass().getName(), obj);
	}

	/**
	 * 将已有对象放入单例中,key做为键
	 *
	 * @param key 键
	 * @param obj 对象
	 * @since 5.3.3
	 */
	public static void put(String key, Object obj) {
		POOL.put(key, obj);
	}

	/**
	 * 判断某个类的对象是否存在
	 *
	 * @param clazz 类
	 * @param params 构造参数
	 * @return 是否存在
	 */
	public static boolean exists(Class<?> clazz, Object... params){
		if (null != clazz){
			final String key = buildKey(clazz.getName(), params);
			return POOL.containsKey(key);
		}
		return false;
	}

	/**
	 * 获取单例池中存在的所有类
	 *
	 * @return 非重复的类集合
	 */
	public static Set<Class<?>> getExistClass(){
		return POOL.values().stream().map(Object::getClass).collect(Collectors.toSet());
	}

	/**
	 * 移除指定Singleton对象
	 *
	 * @param clazz 类
	 */
	public static void remove(Class<?> clazz) {
		if (null != clazz) {
			remove(clazz.getName());
		}
	}

	/**
	 * 移除指定Singleton对象
	 *
	 * @param key 键
	 */
	public static void remove(String key) {
		POOL.remove(key);
	}

	/**
	 * 清除所有Singleton对象
	 */
	public static void destroy() {
		POOL.clear();
	}

	// ------------------------------------------------------------------------------------------- Private method start

	/**
	 * 构建key
	 *
	 * @param className 类名
	 * @param params    参数列表
	 * @return key
	 */
	private static String buildKey(String className, Object... params) {
		if (ArrayUtil.isEmpty(params)) {
			return className;
		}
		return StrUtil.format("{}#{}", className, ArrayUtil.join(params, "_"));
	}
	// ------------------------------------------------------------------------------------------- Private method end
}

3.ReflectUtil工具类

可通过反射,通过class文件来创建出来bean对象

public static <T> T newInstance(Class<T> clazz, Object... params) throws UtilException {
		if (ArrayUtil.isEmpty(params)) {
			final Constructor<T> constructor = getConstructor(clazz);
			if (null == constructor) {
				throw new UtilException("No constructor for [{}]", clazz);
			}
			try {
				return constructor.newInstance();
			} catch (Exception e) {
				throw new UtilException(e, "Instance class [{}] error!", clazz);
			}
		}

		final Class<?>[] paramTypes = ClassUtil.getClasses(params);
		final Constructor<T> constructor = getConstructor(clazz, paramTypes);
		if (null == constructor) {
			throw new UtilException("No Constructor matched for parameter types: [{}]", new Object[]{paramTypes});
		}
		try {
			return constructor.newInstance(params);
		} catch (Exception e) {
			throw new UtilException(e, "Instance class [{}] error!", clazz);
		}
	}
	
public static <T> Constructor<T> getConstructor(Class<T> clazz, Class<?>... parameterTypes) {
		if (null == clazz) {
			return null;
		}

		final Constructor<?>[] constructors = getConstructors(clazz);
		Class<?>[] pts;
		for (Constructor<?> constructor : constructors) {
			pts = constructor.getParameterTypes();
			if (ClassUtil.isAllAssignableFrom(pts, parameterTypes)) {
				// 构造可访问
				setAccessible(constructor);
				return (Constructor<T>) constructor;
			}
		}
		return null;
	}	

标签:Singleton,return,对象,param,clazz,params,单例
From: https://www.cnblogs.com/PythonOrg/p/17645914.html

相关文章

  • 设计模式-单例模式
    饿汉式/***饿汉式,类加载的时候就会初始化**问题:*1.通过反射可以破坏单例*2.通过反序列化破坏单例*3.通过Unsafe破坏单例,无法解决**@author:optimjie*@date:2023-08-1921:37*/publicclassSingleton1{privateSingleton1()......
  • 【补充】Python中实现单例模式的六种常见方法
    【补充】Python中实现单例模式的六种常见方法【1】类属性:classSingleton:instance=None@classmethoddefgetInstance(cls):ifcls.instanceisNone:cls.instance=Singleton()returncls.instance使用类属性保存实......
  • 单例
    /**FileName:MonoSingleton.cs*Author:AUTHOR*Date:2023/08/1513:12:41*UnityVersion:2021.3.15f1c1*Description:*/usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;///<summary>///Mono单例类///<......
  • 7种创建方式,带你理解Java的单例模式
    本文分享自华为云社区《《Java极简设计模式》第01章:单例模式(Singleton)》,作者:冰河。单例设计模式看几个单例对象的示例代码,其中有些代码是线程安全的,有些则不是线程安全的,需要大家细细品味,这些代码也是在高并发环境下测试验证过的。代码一:SingletonExample1这个类是懒汉模式......
  • 7种创建方式,带你理解Java的单例模式
    本文分享自华为云社区《《Java极简设计模式》第01章:单例模式(Singleton)》,作者:冰河。今天给大家介绍Java极简设计模式中的单例设计模式(Singleton),用最短的篇幅讲述设计模式最核心的知识。单例设计模式看几个单例对象的示例代码,其中有些代码是线程安全的,有些则不是线程安全的,需要大家细......
  • 8-16|Python操作3Dmax简单例子
    是的,Python可以与3dsMax交互。Autodesk3dsMax提供了一个名为`MaxPlus`的PythonAPI,可以使开发人员使用Python控制和自动化3dsMax。使用这个API,你可以创建、查询和编辑场景对象,控制动画,以及完成3dsMax内的许多其他任务。以下是使用Python与3dsMax交互的基本步骤:1.**安装3ds......
  • 1.单例模式
    单例模式定义:程序运行时,在java虚拟机中只存在该类的一个实例对象。demo:packagemode;publicclassSingleDemo{//创建SingleDemo单例对象privatestaticSingleDemoinstance=newSingleDemo();//将构造方法设成私有的,这样该类就不会被实例化pri......
  • 单例模式
    双重锁解释双重if是需要的。如果只有一重,还是可能初始化两次valatile是要得。uniqueInstance=newSingleton();这段代码其实是分为三步执行:为uniqueInstance分配内存空间初始化uniqueInstance将uniqueInstance指向分配的内存地址但是由于JVM具有指令重排的......
  • 单例模式的理论与实现
    本文实践代码仓库:https://github.com/goSilver/my_practice目录一、定义二、作用三、实现3.1饿汉式3.2懒汉式3.3双重检查3.4静态内部类3.5枚举四、总结4.1单例存在哪些问题?4.2单例有什么替代解决方案?一、定义单例模式是一种创建型设计模式,它确保一个类只有一个实例,并......
  • Java单例模式详解
    Java单例模式详解单例模式是设计模式中的一种,它确保某一个类只有一个实例,并提供一个全局点来访问这个实例。这在某些场景中是非常有用的,例如,配置管理、线程池、缓存、日志对象等。1.单例模式的基本原则:构造函数是私有的。有一个私有静态变量来保存类的唯一实例。有一个公有静态方......