GoF之单例模式详解

本文详细介绍了GoF的单例模式,阐述了其定义、应用场景和优点。单例模式常用于控制资源的全局访问,如任务管理器、数据库连接池等。文章列举了不同实现方式,包括饿汉式、懒汉式、双重检测锁式、静态内部类式和枚举单例,并分析了各自的线程安全性和效率。在选择单例实现时,静态内部类式适用于延时加载,而枚举式则适合不需要延时加载的情况。

GoF 23种设计模式的分类表:

GoF之单例模式详解

 

 

定义及场景:

保证一个类只能生成一个实例,并且提供一个访问该实例的全局访问点。

例如,Windows 中只能打开一个任务管理器,这样可以避免因打开多个任务管理器窗口而造成内存资源的浪费,或出现各个窗口显示内容的不一致等错误。还有 Windows 的回收站、操作系统中的文件系统、多线程中的线程池、显卡的驱动程序对象、打印机的后台处理服务、应用程序的日志对象、数据库的连接池、网站的计数器、Web 应用的配置对象、应用程序中的对话框、Spring中Bean、Servlet等常常被设计成单例。

优点:

由于单例模式只生成一个实例,减少了系统性能的开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留在内存中的方式来解决。

单例模式可以在系统设置全局的访问点,优化环共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理。

常见单例模式实现方式:

饿汉式(线程安全,调用效率高。不能延时加载)

//问题:如只加载本类,而不需要调用getInstance(),则造成资源浪费。
public class SingletonTest
{
 //类初始化时,立即加载这个对象(没有延时加载的优势)
 //静态变量加载是天然的线程安全
 private static SingletonTest singletonTest = new SingletonTest();
 //构造器私有化
 private SingletonTest() {
 }
 //定义一个全局的访问点,访问这个单例对象,方法没有同步,调用效率高
 public static SingletonTest getInstance(){
 return singletonTest;
 } 
}

懒汉式(线程安全,调用效率不高。可延时加载。单线程可以去掉同步块来提高效率)

//问题:每次调用getInstance()方法都要同步,并发效率较低。
public class SingletonTest
{
 //类初始化时,不会立即加载这个对象,用到时再创建
 private static SingletonTest singletonTest;
 //构造器私有化
 private SingletonTest(){
 }
 //方法同步,调用效率较低
 public static synchronized SingletonTest getInstance(){
 if(singletonTest == null){
 singletonTest = new SingletonTest();
 }
 return singletonTest;
 } 
}

双重检测锁式(使用较少)

//问题:同样功能下,代码量最大。
public class SingletonTest
{
 private static SingletonTest singletonTest = null;
 private SingletonTest(){
 }
 public static SingletonTest getInstance(){
 if(singletonTest == null){
 SingletonTest st;
 //只有第一次实例化才需要同步,提高了执行效率
 synchronized (SingletonTest.class){
 st = singletonTest;
 if(st == null){
 synchronized(SingletonTest.class) {
 st = new SingletonTest();
 }
 }
 singletonTest = st;
 }
 }
 return singletonTest;
 }
}

静态内部类式(线程安全,调用效率高。可以延时加载)

//外部类没有static属性,不会立即加载对象。兼备了并发高效调用和延时加载的优势
public class SingletonTest
{
 private SingletonTest(){
 }
 //singletonTest是staticfinal类型,保证了内存中只有一个这样的实例存在,而且只能被赋值一次,从而保证了线程安全性
 private static class SingletonClassInatance{
 private static final SingletonTest singletonTest = new SingletonTest();
 }
 //只有真正调用getInstance(),才会加载静态内部类。加载类时是线程安全的。
 public static singletonTest getInstance(){
 return SingletonClassInatance.singletonTest;
 } 
}

枚举单例(线程安全,调用效率高,不能延时加载)

//枚举式单例模式实现(没有延时加载)
public enum SingletonTest
{
 //定义一个枚举元素,它本身就代表了SingletonTest的一个单例
 INSTANCE;
 //添加自己需要的操作!
 public void singletonOperation(){
 
 }
}

用单例,选哪个?

延时加载中,静态内部类式效率优于懒汉式。

不需要延时加载中,枚举式效率优于饿汉式。

 


免费分享Java技术资料,需要的朋友可以先关注后私信我,免费获取

GoF之单例模式详解

 

GoF之单例模式详解

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值