摘要:简介最基本的实例中规定了一个类只会被初始化一次所以该方法是线程安全的但是其在方法调用前就初始化了比较浪费资源优点只有一个实例节约内存空间减少了系统的性能开销如果某一个对象的产生需要比较多的资源时可以在启动时直接产生一个单例对象使其永驻内存可
In software engineering, the singleton pattern is a software design pattern that restricts the instantiation of a class to one object. This is useful when exactly one object is needed to coordinate actions across the system. The concept is sometimes generalized to systems that operate more efficiently when only one object exists, or that restrict the instantiation to a certain number of objects. The term comes from the mathematical concept of a singleton简介 最基本的实例
public class Emperor { private static final Emperor emperor=new Emperor(); private Emperor(){} public static Emperor getInstance(){ return emperor; } }
Java Language Specification 中规定了一个类只会被初始化一次.所以该方法是线程安全的, 但是其在方法调用前就初始化了, 比较浪费资源.
优点只有一个实例, 节约内存空间, 减少了系统的性能开销, 如果某一个对象的产生需要比较多的资源时, 可以在启动时直接产生一个单例对象, 使其永驻内存.
可以避免对资源的多重占用,
可以在系统设置全局的访问点, 优化和共享资源访问.
缺点单例模式一般没有接口, 扩展很困难, 除了修改代码基本上没有第二种途径可以实现
单例模式不利于测试, 如果单例模式没有完成, 无法进行测试
与单一职责原则相冲突.
其它实现方式 懒汉模式class Singleton { private static Singleton instance; private Singleton(){} public static synchronized Singleton getInstance(){ if(instance==null){ instance=new Singleton(); } return instance; } }
该实现只会在需要的时候才会进行初始化且是线程安全的, 但是每次调用getInstance()都会进行同步, 会浪费资源
Double Check Lockclass SingletonDCL{ private static SingletonDCL sInstance; private SingletonDCL(){} public static SingletonDCL getInstance(){ if(sInstance==null){ synchronized (SingletonDCL.class){ if(sInstance==null){ sInstance=new SingletonDCL(); } } } return sInstance; } }
该实现只会在需要的时候才会进行初始化, 看似线程安全, 但实际并不是.
假设线程A执行到sInstance=new SingletonDCL(), 这句代码并不是一个原子操作, 这句代码大致会被分为下面3个步骤来处理:
给SingletonDCL的实例分配内存
调用SingletonDCL的构造函数, 初始化成员字段
将sInstance对象指向分配的内存空间 (此时sInstance就不是null了).
如果这句代码严格按照这个顺序执行,该DCL单例模式便是线程安全的, 但是事实并非如此. 原因是JVM并没有保证上述第2和第3步的执行顺序.
也就是说执行步骤可能是1-3-2, 这种执行步骤就会出问题:
当先执行第3步时, 另一个线程B开始执行getInstance(), 由于此时sInstance已经不是null了, 所以线程B会返回一个还未初始化的sInstance, 出现了错误.
JVM1.5之后改善了这个问题, 在sInstance前加上volatile关键字可以确保线程安全.
即private static volatile SingletonDCL sInstance;
DCL单例模式并不推荐使用,《Java并发编程实践》推荐使用下面这个方法:
class SingletonStatic{ private SingletonStatic(){} public static SingletonStatic getInstance(){ return SingletonStaticHolder.sInstance; } private static class SingletonStaticHolder{ private static final SingletonStatic sInstance=new SingletonStatic(); } }
第一次加载时, 并不会初始化sInstance, 只在第一调用getInstance()时初始化, 且该方法是线程安全的.
枚举单例enum SingletonEnum{ INSTACNE; public void doSomething(){ StdOut.println("doSomething..."); } }
枚举单例模式有以下3个优点:
线程安全, 任何时候都只有一个实例
反序列化时, 都只会有一个实例
可以防止反射攻击
选择哪一种实现方式无论采用哪一种实现方式, 都要确保线程安全, 防止反序列化导致重新生成实例对象等一些问题. 具体选择哪一种实现方式取决于项目本身.
关于序列化除了枚举单例, 为了避免单例对象在被反序列化时重新生成对象, 必须加入以下方法
private Object readResolve() throws ObjectStreamException{ return sInstance; }
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/71722.html
摘要:总结单例是运用频率很高的模式,因为客户端没有高并发的情况,选择哪种方式并不会有太大的影响,出于效率考虑,推荐使用和静态内部类实现单例模式。 单例模式介绍 单例模式是应用最广的模式之一,也可能是很多人唯一会使用的设计模式。在应用单例模式时,单例对象的类必须保证只用一个实例存在。许多时候整个系统只需要一个全局对象,这样有利于我么能协调整个系统整体的行为。 单例模式的使用场景 确保某个类有且...
摘要:不符合设计模式中的单一职责的概念。引入代理实现单例模式引入代理实现单例模式的特点我们负责管理单例的逻辑移到了代理类中。的单例模式对比在以上的代码中实现的单例模式都混入了传统面向对象语言的特点。 声明:这个系列为阅读《JavaScript设计模式与开发实践》 ----曾探@著一书的读书笔记 1.单例模式的特点和定义 保证一个类仅有一个实例,并且提供一个访问它的全局访问点。 2.传统面向对...
摘要:但是,这并不是采用单例的唯一原因。使用命名空间单例模式也被称为模块设计模式。函数内部声明了一些局部函数和或变量。紧随函数声明放置即可立即执行外部函数,并将所得的对象文字费赔给变量。 JavaScript设计模式-第一部分:单例模式、组合模式和外观模式 设计模式是一些可靠的编程方式,有助于保证代码更加易于维护、扩展及分离,所有设计模式在创建大型JavaScript应用程序时均不可或缺 单...
摘要:如果需要防范这种攻击,请修改构造函数,使其在被要求创建第二个实例时抛出异常。单例模式与单一职责原则有冲突。源码地址参考文献设计模式之禅 定义 单例模式是一个比较简单的模式,其定义如下: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 或者 Ensure a class has only one instance, and provide a global point of ac...
摘要:在设计模式一书中,将单例模式称作单件模式。通过关键字,来保证不会同时有两个线程进入该方法的实例对象改善多线程问题为了符合大多数程序,很明显地,我们需要确保单例模式能在多线程的情况下正常工作。 在《Head First 设计模式》一书中,将单例模式称作单件模式。这里为了适应大环境,把它称之为大家更熟悉的单例模式。 一、了解单例模式 1.1 什么是单例模式 单例模式确保一个类只有一个实例,...
阅读 2545·2021-11-23 09:51
阅读 3103·2019-08-30 15:54
阅读 1051·2019-08-30 14:14
阅读 3499·2019-08-30 13:59
阅读 1354·2019-08-29 17:09
阅读 1443·2019-08-29 16:24
阅读 2828·2019-08-29 15:43
阅读 888·2019-08-29 12:45