`
tianlihu
  • 浏览: 311114 次
  • 性别: Icon_minigender_1
  • 来自: 石家庄
社区版块
存档分类
最新评论

Java 单例模式 工具类

阅读更多
本文版权归作者所有,仅供用来网上学习来用,读者可以收藏,请不要下载到本机和重新发布到其它网站

有觉得可以改进的,请留言,也可加群讨论71326533

我们在实际开发中,会大量采用单例模式。但是我们常常疲于写那几个单调的方法,还可考虑同步的问题,下面就是一个常用的单例模式的写法:
public class Singleton {

	private Singleton() {
	}
	... ...
	... ...
}

为了减少重复的写这些无聊的代码,我写了一个类,用来统一管理这些单例对象
import java.lang.reflect.Constructor;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

public class SingletonFactory {

	public static final Logger LOG = Logger.getLogger(SingletonFactory.class.getCanonicalName());

	private static final Map<Class<?>, Object> INSTANCE_MAP = Collections.synchronizedMap(new HashMap<Class<?>, Object>());
	private static final Object[] EMPTY_ARGS = new Object[0];

	/**
	 * <pre>
	 * 用此方法有一个前提:
	 * 参数类必须有显示声明的无参构造器或没有任何显示声明的构造器
	 * </pre>
	 */
	public static <T> T getInstance(Class<? extends T> clazz) {
		return getInstance(clazz, EMPTY_ARGS);
	}

	/**
	 * <pre>
	 * 用此方法有两个前提:
	 * 1. 参数数组的项都不能为null
	 * 2. 参数数组的项都不能是简单数据类型
	 * </pre>
	 */
	public static <T> T getInstance(Class<? extends T> clazz, Object... args) {
		Object object = INSTANCE_MAP.get(clazz);
		if (object == null) {
			Class<?>[] parameterTypes = new Class<?>[args.length];
			for (int i = 0; i < args.length; i++) {
				parameterTypes[i] = args[i].getClass();
			}
			return getInstance(clazz, parameterTypes, args);
		}
		return clazz.cast(object);
	}

	/**
	 * <pre>
	 * 用此方法有三个前提:
	 * 1. 两个参数数组同时为null或同时不为null
	 * 2. 两个数组的长度必须相等
	 * 3. parameterTypes如果不空null, 则其各元素不能为null
	 * </pre>
	 */
	public static <T> T getInstance(Class<? extends T> clazz, Class<?>[] parameterTypes, Object[] args) {
		Object object = INSTANCE_MAP.get(clazz);
		if (object == null) { // 检查实例,如是不存在就进行同步代码区
			synchronized (clazz) { // 对其进行锁,防止两个线程同时进入同步代码区
				// 双重检查,非常重要,如果两个同时访问的线程,当第一线程访问完同步代码区后,生成一个实例;当第二个已进入getInstance方法等待的线程进入同步代码区时,也会产生一个新的实例
				if (object == null) {
					try {
						if (parameterTypes != null && args != null) {
							if (parameterTypes.length == args.length) {
								Constructor<?> constructor = clazz.getDeclaredConstructor(parameterTypes);
								constructor.setAccessible(true);
								T instance = clazz.cast(constructor.newInstance(args));
								INSTANCE_MAP.put(clazz, instance);
								return instance;
							} else {
								throw new IllegalArgumentException("参数个数不匹配");
							}
						} else if (parameterTypes == null && args == null) {
							T instance = clazz.newInstance();
							INSTANCE_MAP.put(clazz, instance);
							return instance;
						} else {
							throw new IllegalArgumentException("两个参数数组必须同时为null或同时不为null");
						}
					} catch (Exception e) {
						LOG.log(Level.SEVERE, "创建实例失败", e);
					}
				}
			}
		}
		return null;
	}
}


用法很简单
public class SingletonTest {

	public static void main(String[] args) {
		Singleton obj1 = SingletonFactory.getInstance(Singleton.class);
		Singleton obj2 = SingletonFactory.getInstance(Singleton.class);
		System.out.println(obj1 == obj2);
	}
}

结果:
true

这里统一管理这些单例对象,且单例对象的构造器可以为私有的。如果需要带参数,则需要使用public static <T> T getInstance(Class<? extends T> clazz, Class<?>[] parameterTypes, Object[] args)方法


4
0
分享到:
评论

相关推荐

    Java单例模式下的MongoDB数据库操作工具类

    主要介绍了Java单例模式下的MongoDB数据库操作工具类,结合实例形式分析了java基于单例模式下操作MongoDB数据库相关连接、查询、插入、删除等操作封装技巧,需要的朋友可以参考下

    单例模式案例和笔记,通过案例来了解单例模式

    Java一共有23种设计模式,单例模式就是指一个类只有一个实例,且该类能自行创建这个实例的一种模式。可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。比如咱们电脑...

    JAVA数据库工具类

    数据库工具类,采用的DBCP的连接池。并且采用了Google公司的工程师Bob Lee写的新的懒汉单例模式来构造连接工厂。并将获取到的数据库连接绑定到当前线程中。这样可以有效的防止申请连接的滥用。

    java设计模式

    目录: 前 言 第一部分 大旗不挥,谁敢冲锋——热身篇 第1章 单一职责原则 1.1 我是“牛”类,我可以担任多职吗 1.2 绝杀技,打破你的传统思维 ...38.1.5 工具类 38.2 最佳实践 附录:23个设计模式

    实验5 JAVA常用类.doc

    本专栏主要为Java程序设计(基础)实验报告和Java程序设计(进阶)...进阶篇有反射、泛型、注解、网络编程、多线程、序列化、数据库、Servlet、JSP、XML解析、单例模式与枚举。本专栏主要为Java入门者提供实验参考。

    JAVA单例模式源码-setupmaker:DCP设置工具

    JAVA例单模式源码DCP 设置工具 用于生成复杂、稳定和跨平台的 Java 安装程序的 Java 程序。 观看在 2 分钟内制作的 DCP Setup Maker 安装程序的演示: “其直观的用户界面和卓越的易用性使得构建包含大量文件的复杂...

    基于Java的设计模式大作业绘图系统【六种设计模式+文档】.zip

    本系统基于六种设计模式,运用到的设计模式有备忘录模式,简单工厂模式,迭代器模式,状态模式,模版方法模式,单例模式。 具体实现过程、UML类图以及实现效果详见如下项目说明地址: ... 该系统为绘图系统,该系统通过...

    JAVA单例模式源码-xapi:XApi-极其可扩展的跨平台API

    接口绑定到实现类,无论是在单例还是实例范围内。 主要目标是使用 构建的 Web 服务器和客户端应用程序,不过也在名为 . 使用这个核心工具,每个其他模块都被构建为一个独立的服务,旨在通过可以轻松覆盖的接口公开...

    GOF23之单例模式

    在Java,一般常用在工具类的实现或创建对象需要消耗资源。 常见应用场景: 1、任务管理器 2、回收站 3、网站计数器 4、数据库连接池 优点: 1、单例模式只能产生一个实例,减少了系统性能的开销,当一个对象的产生...

    java的工具api

    这是一款很好用的API工具,是每个程序员所必备的工具

    设计模式(Java源码示例,超经典).rar

    4.注释非常全,除了跟模式无关的辅助工具类的每一个类,每一个方法,每一个属性都有注释; 5.每一种模式都分配一个readme文件做为说明; 6.除了最简单的单例模式,每一种模式都有&gt;=2套示例代码; 7.这都是在网上找了...

    JAVA单例模式源码-goaop-laravel-bridge:Go的集成桥接器!AOP框架和Laravel

    JAVA例单模式源码高桥 GoAopBridge 通过 Go 添加了对面向方面编程的支持! Laravel5 应用程序的 AOP 框架。 概述 面向方面的范式允许使用特殊工具扩展标准的面向对象范式,以有效解决应用程序中的横切关注点。 此...

    自己收集整理的一些常用的工具类

    DeviceStatusUtils 手机状态工具类 主要包括网络、蓝牙、屏幕亮度、飞行模式、音量等 DigestUtils DigestUtils FileUtils 文件操作 HanziToPinyin 拼音汉字处理 IOUtils IOUtils MD5 MD5 MiscUtils 设备信息的获取 ...

    用enum实现单例模式的方法来读取配置文件

    NULL 博文链接:https://java--hhf.iteye.com/blog/2171034

    java经典面试题目-面经-java-Java语言的进阶概念-常用的库和框架-并发编程-网络编程-Web开发-面经

    什么是Java中的单例模式?如何实现线程安全的单例模式? 什么是Java中的生命周期回调方法?列举一些常见的生命周期回调方法。 什么是Java中的注解处理器?如何自定义和使用注解处理器? 什么是Java中的并发编程?...

    实验2 Java语言基础.doc

    本专栏主要为Java程序设计(基础)实验报告和Java程序设计(进阶)...进阶篇有反射、泛型、注解、网络编程、多线程、序列化、数据库、Servlet、JSP、XML解析、单例模式与枚举。本专栏主要为Java入门者提供实验参考。

    一个java正则表达式工具类源代码.zip(内含Regexp.java文件)

    以前写了一个java的正规表达式的java工具类,分享一下,有用到的欢迎下载使用。 如果你有常用的定义好的,且测试通过的正规表达式,欢迎跟贴,也让我享用一下 . 类中用到了 jakarta-oro-2.0.jar 包,请大家自己在 ...

    Java基础知识点总结.docx

    Collections--集合工具类 83 Arrays—数组对象工具类 84 增强for循环 85 可变参数(...) 86 枚举:关键字 enum 86 自动拆装箱 86 泛型 87 &lt;java.lang&gt;System 89 &lt;java.lang&gt;Runtime 90 &lt;java.lang&gt;Math 90 &lt;java....

    【白雪红叶】JAVA学习技术栈梳理思维导图.xmind

    单例模式 行为模式 责任链模式 命令模式 解释器模式 迭代器模式 中介者模式 备忘录模式 观察者模式 状态模式 策略模式 模板方法模式 访问者模式 设计案例 UML 架构 系统架构能力 基本理论 扩展性...

Global site tag (gtag.js) - Google Analytics