单例模式
定义
Ensure a class has only one instance , and provide a global point of access to it.
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
单例模式示意图
![单例模式]()
流程
- 客户向单例提供者请求实例
- 单例提供者使用类名.getInstance()从单例类中获取唯一实例
- 这个唯一实例在单例类中先被创建(单例类只能创建一个实例)。单例类通过暴露getInstance()这个静态方法,让外界可以获取这个单个实例。
代码实现
- 普通单例模式(饿汉式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
public class SingleTonCommon { private static final SingleTonCommon singleTon = new SingleTonCommon();
private SingleTonCommon(){
}
public static SingleTonCommon getInstance(){ return singleTon ; }
public static void test(){ System.out.println("普通单例模式(饿汉式)"); }
public void getTest(){ test(); } }
|
- 普通单例模式(懒汉式)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
public class SingleTonCommon2 { private static SingleTonCommon2 singleTon ;
private SingleTonCommon2(){
}
public static SingleTonCommon2 getInstance(){ if (singleTon == null){ singleTon = new SingleTonCommon2(); } return singleTon ; }
public static void test(){ System.out.println("普通单例模式(懒汉式)"); }
public void getTest(){ test(); } }
|
- synchronized单例模式(懒汉式线程安全版)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
|
public class SingleSynchronized { private static SingleSynchronized singleTon ;
private SingleSynchronized(){
}
public static SingleSynchronized getInstance(){ if (singleTon == null){ synchronized (SingleSynchronized.class){ if (singleTon == null){ singleTon = new SingleSynchronized(); } } } return singleTon ; }
public static void test(){ System.out.println("synchronized单例模式"); }
public void getTest(){ test(); } }
|
- volatile单例模式(懒汉式线程安全版)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
public class SingleTonVolatitle { private volatile static SingleTonVolatitle singleTon ;
private SingleTonVolatitle(){
}
public SingleTonVolatitle getInstance(){ if (singleTon == null) { singleTon = new SingleTonVolatitle(); } return singleTon ; }
public static void test(){ System.out.println("volatile单例模式"); }
public void getTest(){ test(); } }
|
- 静态内部类单例模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
public class SingleTonStaticInner { private SingleTonStaticInner(){
}
public SingleTonStaticInner getInstance(){ return Inner.singleTon ; }
private static class Inner{ private static final SingleTonStaticInner singleTon = new SingleTonStaticInner(); } }
|
- 枚举单例模式
1 2 3 4 5 6 7 8 9 10 11 12 13
|
public enum SingleTonEnum { INSTANCE; public static SingleTonEnum Instance(){ return SingleTonEnum.INSTANCE ; } }
|
- 静态代码块单例模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
public class SingleTonStatic { private static SingleTonStatic singleTon ; private SingleTonStatic(){
}
static { singleTon = new SingleTonStatic(); } }
|
应用场景
- 要求生成唯一序列号的环境。
- 在整个项目中需要一个共享访问点或共享数据,例如一个web页面的计数器,不用把每次刷新都记录到数据库,使用单例模式保持计数器的值,并确保线程安全。
- 创建一个对象需要消耗的资源很多,如要访问IO或数据库。
- 需要定义大量的静态常量或静态方法。
单例模式优缺点
优点
- 对象的创建会占用内存,只有一个实例对象,这样减少内存开支。
- 对象会占用系统资源,只有一个实例对象,会减少系统性能开销。
- 多个实例在内存中可能会产生对多重占用问题,单例模式可以避免这种情况发生。
- 单例模式可以在全局设置一个访问点,这样可以优化和共享资源访问。
缺点
- 没有接口,扩展困难。
- 在并发环境下,单例模式没有完成是不能进行测试的,也不能使用mock虚拟一个对象。
- 单例模式与单一职责原则有冲突。
单例的扩展
能产生固定数量对象的模式叫有上限的多例模式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import java.util.ArrayList;
public class SingleTonExtension { private static int maxNumSingleTon = 2 ;
private static ArrayList<SingleTonExtension> singleTons = new ArrayList<>();
private SingleTonExtension(){
}
static { for (int i=0 ; i<maxNumSingleTon ; i++) { singleTons.add(new SingleTonExtension()); } } }
|
文献引用
- Java双重校验锁实现单例模式
- 设计模式之单例模式
- volatile
- Java 枚举
- Java之static静态代码块
- 深入理解单例模式:静态内部类单例原理