Java设计设计模式之单例模式(Singleton)
单例模式在日常应用开发过程中被大量使用到,如在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。
单例模式的特点如下:
1、运行时只有一个实例供其他对象使用,同时只允许创建唯一一个实例
2、对象的初始化工作由自身来完成
3、从对象的加载方式来分,可分为乐观加载和悲观加载两种方式
单例模式应用的场景一般发现在以下条件下:
(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。
(2)控制资源的情况下,方便资源之间的互相通信。如线程池等。
设计单例类的过程中,有些人觉得分情况考虑,你可以设计成线程安全的单例模式和线程不安全的,其实在现在互联网应用满天飞的今天,养成良好的习惯,设计的时候你只考虑线程安全的会对以后的帮助比较大,至于性能方面的考虑,可以不用在乎, 毕竟通常情况下应用的性能瓶颈往往都是架构设计层面导致的,和一个小小的模块内部的实现细节有关系,但影响没有想象中的那么大。系统的核心性能问题还是要从架构层面入手去考虑设计。
1、乐观加载的单例模式
/** * 乐观加载 * * @author Administrator * @version $Id: Singleton.java, v 0.1 2017年3月11日 下午6:59:43 Administrator Exp $ */ public class Singleton { /** */ private static Singleton _inst = null; /** * 乐观加载,相信在使用时加载也来得及 * * @return */ public static Singleton getInstance() { if (_inst == null) { synchronized (Singleton.class) { _inst = new Singleton(); System.out.println("init instance first time"); } } System.out.println("its ready, just get it"); return _inst; } public static void main(String[] args) { Singleton.getInstance(); Singleton.getInstance(); Singleton.getInstance(); } }
运行结果:
init instance first time its ready, just get it its ready, just get it its ready, just get it
这种方式的优势是,在系统启动过程中减少了系统启动的时间,单例类内部的实际加载过程是在系统第一次被使用时才去完成,因此这种模式也被叫做惰性单例模式。
这种模式下的类实例初始化动作需要比较小心,因为初始化是在第一次使用时,因此类实例在定义时,无法定义成常量,最多只能定义成一个静态的对象,而第一次触发初始化动作的请求有可能并发进来很多,为了避免短时间内的频繁初始化带来一些不可预期的结果,在初始化的过程中需要选择在同步块中完成。
2、悲观加载的单例模式
/** * 悲观加载 * * @author Administrator * @version $Id: Singletonn.java, v 0.1 2017年3月11日 下午7:09:40 Administrator Exp $ */ public class Singletonn { /** */ private static final Singleton _inst = new Singleton(); /** * 乐观加载,相信在使用时加载也来得及 * * @return */ public static Singleton getInstance() { System.out.println("its ready, just get it"); return _inst; } public static void main(String[] args) { Singleton.getInstance(); } }
这种方式比较简单,对象实例的初始化是通过一个常量直接完成的,但经常需要初始化的实例往往要比我们例子复杂很多,所以会出现一些这两种方式综合使用的变种单例模式
import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * 悲观加载 * * @author Administrator * @version $Id: Singletonn.java, v 0.1 2017年3月11日 下午7:09:40 Administrator Exp $ */ public class Singletonn { /** */ private static final Map<String, Singleton> _inst = Collections .synchronizedMap(new HashMap<String, Singleton>()); static { synchronized (_inst) { _inst.put("key1", Singleton.getInstance()); _inst.put("key2", Singleton.getInstance()); _inst.put("key3", Singleton.getInstance()); } } /** * 乐观加载,相信在使用时加载也来得及 * * @return */ public static Singleton getInstance() { return new Singleton(); } public static void main(String[] args) { Singleton.getInstance(); } }
其中,静态块中的内容,我们可以理解为,是在初始化过程中需要完成的一系列的业务处理,当然这里还会有其他很多的单例类演化方式,但万变不离其宗,只要了解了基本的情况,后面的变种,只是自己在后续的实际使用场景中灵活处理的方式而已,没必要去死记这些东西。
各位看官,原创不易啊,转载请注明出处: http://danlley.iteye.com 看在打字不易的份上,打赏一个吧
参考资料:
http://blog.csdn.net/tanyujing/article/details/14160941
http://blog.csdn.net/jason0539/article/details/23297037/