1 单例模式定义与结构
为了节约系统资源,有时需要确保系统中某个类只有唯一一个实例,当这个唯一实例创建成功之后,我们无法再创建一个同类型的其他对象,所有的操作都只能基于这个唯一实例。为了确保对象的唯一性,我们可以通过单例模式来实现,这就是单例模式的动机所在。单例模式定义如下(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式。单例模式有三个要点:一是某个类只能有一个实例;
二是它必须自行创建这个实例;
三是它必须自行向整个系统提供这个实例。
单例模式是结构最简单的设计模式一,在它的核心结构中只包含一个被称为单例类的特殊类。单例模式结构如图所示:
如上图所示,单例模式只包含一个单例角色:Singleton(单例),在单例类的内部实现只生成一个实例,同时它提供一个静态的getInstances()工厂方法,让客户可以访问它的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。
2 饿汉式单例类和懒汉式单例类
(1)饿汉式单例类:当类被加载时,静态变量instance会被初始化,此时类的私有构造函数会被调用,单例类的唯一实例将被创建,可确保单例对象的唯一性。
package com.sxh.singleton;
public class SingleTon {
/*
* volatile关键字确保:当uniqueInstance变量被初始化为SingleTon实例时,多个线程能正确的处理uniqueInstance变量
* 分析:volatile修饰的成员变量,在每次被线程访问时,都强制性的从共享内存重读该成员的值;
* 当值发生变化是,强制线程将变化值写入共享内存,任何时候不同线程总是看到你某个成员变量的同一个值
* */
private volatile static SingleTon uniqueInstance;//利用一个静态变量来记录SingleTon类的唯一实例
//其他有用的单件类的数据
private SingleTon(){} //类外无法访问
public static SingleTon getInstance(){
/*
* 使用”双重检查加锁“,在getInstance中减少使用同步
* 首先检查是否实例已经创建了,如果尚未创建,才进行同步;只有第一次访问getInstance会同步
*/
if(uniqueInstance==null){ //确保只有一个实例
synchronized (SingleTon.class) { //多线程的情况不会出现问题,线程同步问题
if(uniqueInstance==null){
uniqueInstance=new SingleTon();//如果我们不需要这个实例,则永远不会产生
}
}
}
return uniqueInstance;
}
//其他有用的单件类的方法,单件类也可以是一般的类,具有一般的数据和方法
}
3 一种更好的单例实现方法
饿汉式单例类不能实现延迟加载,不管将来用不用始终占据内存;懒汉式单例类线程安全控制烦琐,而且性能受影响。Initialization Demand Holder (IoDH)的技术。在IoDH中,在单例类中增加一个静态(static)内部类,在该内部类中创建单例对象,再将该单例对象通过getInstance()方法返回给外部使用,可以实现延迟加载,又可以保证线程安全,不影响系统性能,不失为一种最好的Java语言单例模式实现方式(其缺点是与编程语言本身的特性相关,很多面向对象语言不支持IoDH)。
4 总结