一.简介
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例.
二.实现
依次介绍和实现几种单例实现的方法.
1.懒汉-方法1
public class Singleton {
private Singleton() {
}
private static Singleton instance = null;
public static Singleton getInstance() {
if (instance == null) {// 1
instance = new Singleton();
}
return instance;
}
}
PS:具有lazy loading的效果.但却是线程不安全,可能会发现在两个线程重试进入"//1"处的判断,创建两个实例对象
2.懒汉-方法2
public class Singleton {
private Singleton() {
}
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
3.懒汉-方法3(懒汉-方法2的另种写法)
public class Singleton {
private Singleton() {
}
private static Singleton instance = null;
public static Singleton getInstance() {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
}
4.饿汉-方法1
这种方式基于classloder机制避免了多线程的同步的问题,不过,instance在类装载时就实例化,显然没有达到lazy loading(延迟装载)的效果。
public class Singleton {
private Singleton() {
}
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
}
5.饿汉-方法2
这种方式同上,类装载时就会实例化,没有达到lazy loading(延迟装载)的效果。
public class Singleton {
private Singleton() {
}
private static Singleton instance;
static {
instance = new Singleton();
}
public static Singleton getInstance() {
return instance;
}
}
6.双重校验锁
因为多线程同时到"instance==null"的概率是非常低,所以为了避免加锁所带来的性能问题,大神们久设计的下面的结构,即为:双重校验锁
public class Singleton {
private Singleton() {}
private static Singleton instance = null;
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
7.内部静态类(推荐)
public class Singleton {
private Singleton() {
}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
8.枚举(推荐)
//类Resource是我们要应用单例模式的资源
class Resource{
}
//SomeThing.INSTANCE.getInstance() 即可获得所要实例
public enum ResourceInstance {
INSTANCE;
private Resource instance;
ResourceInstance() {
instance = new Resource();
}
public Resource getInstance() {
return instance;
}
}
PS:在枚举中我们定义构造方法限制为私有,在我们访问枚举实例时会执行一次构造方法,同时每个枚举实例都是static final类型的,也就表明只能被实例化一次。在调用构造方法时,我们的单例被实例化。也就是说,因为enum中的实例被保证只会被实例化一次,所以我们的INSTANCE也被保证实例化一次。可以看到,枚举实现单例还是比较简单的。
三.各种单例写法之间的对比
在使用单例的时候基本上我们关注的基本上就是:是否线程安全,是否具有lazy loading效果,和效率.
四.备注及总结
设计模式的学习和掌握可以让我们写的代码更加的具有规范性,设计模式仅是一种实现功能的同时让代码更具有规范性的手段,自然不区分语言.
后面继续补充比较常用的其他设计模式.有什么问题还请各位大牛们给出矫正.