单例模式介绍
概述
单例模式:某一个类在系统中只需要有一个实例对象,而且对象是由这个类自行实例化并提供给系统其它地方使用,这个类称为单例类。单例模式是GOF 23种设计模式中最简单的一种,但同时也是在项目中接触最多的一种。单例模式属于一种创建型设计模式。
使用场景
大家都使用过Windows任务管理器,正常情况下,无论我们在Windows任务栏的右键菜单上点击启动多少次“任务管理器”,系统始终只能弹出一个任务管理器窗口。也就是说,在一个Windows系统中,系统只维护一个任务管理器。这就是一个典型的单例模式运用。
再举一个例子,网站的计数器,一般也是采用单例模式实现,如果你存在多个计数器,每一个用户的访问都刷新计数器的值,这样的话你的实计数的值是难以同步的。但是如果采用单例模式实现就不会存在这样的问题,而且还可以避免线程安全问题。同样多线程的线程池的设计一般也是采用单例模式,这是由于线程池需要方便对池中的线程进行控制。
可以看出,我们在程序中使用单例模式,目的一般是处理资源访问的冲突,或者从业务概念上,有些数据在系统中只应保存一份,那也比较适合设计为单例类,比如配置类、全局流水号生成器等。
UML类图
单例模式实现
单例模式实现要点
单例模式虽然简单,但是要写出一个能保证在多线程环境下也能保证实例唯一性的单例确不是那么简单,实现一个正确的单例模式有以下几个要点:
-
• 1.某个类只能有一个实例,即使是多线程运行环境下;
-
• 2.单例类的实例一定是单例类自身创建,而不是在单例类外部用其它方式如new方式创建;
-
• 3.单例类需要提供一个方法向整个系统提供这个实例对象。
单例两种模式
单例模式分为饿汉模式和懒汉模式,这两种模式很好理解,懒汉模式的意思就是这个类很懒,只要别人不找它要实例,它都懒得创建。饿汉模式在初始化时,我们就创建了唯一的实例,即便这个实例后面并不会被使用。
下面分别介绍两种单例模式的写法。
懒汉式
下面这种写法的单例是大家最简单最容易写出的一种单例写法,只适用于单线程的系统,也就是说它不是线程安全的。
//懒汉式,线程不安全
class Singleton1{
private static Singleton1 instance;
//构造函数定义为私有,防止外部创建实例
private Singleton1(){
}
//系统使用单例的入口
public static Singleton1 getInstance(){
if (null == instance){
instance = new Singleton1();
}
return instance;
}
}
针对线程不安全的问题,可以通过获取实例的方法添加了synchronized来解决,如下:
//懒汉式,线程安全,效率低
class Singleton2{
private static Singleton2 instance;
//构造函数定义为私有,防