1. 单例模式简介
单例模式(Singleton Pattern)是创建型模式(Creational Pattern)的一种,也是最简单的设计模式。顾名思义,单例模式就是只有一个实例,单例类自己创建唯一的实例,并且向其它对象提供这个实例。
单例模式广泛应用于线程池、缓存、日志对象等场景,这些应用场景基本都涉及到资源管理。
2. 单例模式的写法
茴字有四种写法,单例模式也有N种写法,这里我们只准备说三种线程安全的单例模式,分别是饿汉方式、内部类方式、枚举类方式。
2.1 饿汉方式
所谓饿汉,就是明明我就在这里,却没有人来勾搭。单例类在被装载时,单例对象就被实例化,即使永远没人调用,是为饿汉。人们说它的缺点是在没被调用之前实例就被创建了,占用了内存资源;但单例模式占用的资源和内存的价格比起来,实在不值一提。
package org.patterns.creational.singleton;
public class SingleObject {
// 创建单例对象,注意static修饰符。所谓的饿汉模式。
private static SingleObject instance = new SingleObject();
// 将构造器声明成为private,使其不能通过new操作符来操作。
private SingleObject(){}
//获取实例的方法,静态的成员方法。
public static SingleObject getInstance(){
return instance;
}
// 单例提供的功能
public void showMessage(){
System.out.println("Hello World!");
}
}
2.2 内部类方式
内部类的方式保证了仅当单例类被调用时才实例化对象,同时也保证了线程安全;它利用classloader的机制来保证初始化instance时只有一个线程;当getInstance方法被调用时,内部类SingletonHolder才会被装载,从而实例化单例类。
内部类的方式,还能防止通过反射和反序列化的方式获取额外的实例。
public class InnerSingleton {
// 私有构造器
private InnerSingleton(){}
// 内部类
private static class SingletonHolder {
private static final InnerSingleton INSTANCE = new InnerSingleton();
}
//获取实例的方法,静态的成员方法。
public static final InnerSingleton getInstance(){
return SingletonHolder.INSTANCE;
}
// 单例提供的功能
public void showMessage(){
System.out.println("Hello World!");
}
}
2.2 枚举类方式
枚举类方式是《Effective Java》一书所倡导的,需要JDK1.5+的支持。它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象。
public enum EnumSingleton {
INSTANCE;
// 单例提供的功能
public void showMessage(){
System.out.println("Hello World!");
}
}
3. 单例模式的注意事项
-
不同的单例写法,在创建实例的时候,有可能是线程不安全的,可能会导致创建多个实例。
-
单例不是单线程,单例类也可以被多线程并发地调用;Spring中声明的Bean,默认都是单例模式。如果单例类的多个方法存在资源竞争的情况,那么也许需要引入锁机制来解决。
-
如果单例类实现了Serializable接口,如果不做处理,反序列化得到的实例,和序列化之前的实例,并不是同一个,他们的内存地址不相同,这违背了单例模式的初衷。Java的序列化机制提供了一个钩子方法,即私有的readresolve方法,允许我们来控制反序列化时得到的对象。通过这个机制,可以使得反序列化得到的实例,就是唯一的实例。下面的链接里,有相关的介绍。http://www.jianshu.com/p/1d73b49a8a1f
(完)
网友评论