单例模式作为一种目标明确、结构简单、理解容易的设计模式,在软件开发中使用频率相当 高,在很多应用软件和框架中都得以广泛应用。 1.主要优点 单例模式的主要优点如下: (1) 单例模式提供了对唯一实例的受控访问。因为单例类封装了它的唯一实例,所以它可以严 格控制客户怎样以及何时访问它。 (2) 由于在系统内存中只存在一个对象,因此可以节约系统资源,对于一些需要频繁创建和销 毁的对象单例模式无疑可以提高系统的性能。 (3) 允许可变数目的实例。基于单例模式我们可以进行扩展,使用与单例控制相似的方法来获 得指定个数的对象实例,既节省系统资源,又解决了单例单例对象共享过多有损性能的问 题。 2.主要缺点 单例模式的主要缺点如下: (1) 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。 (2) 单例类的职责过重,在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角 色,提供了工厂方法,同时又充当了产品角色,包含一些业务方法,将产品的创建和产品的 本身的功能融合到一起。 (3) 现在很多面向对象语言(如Java、C#)的运行环境都提供了自动垃圾回收的技术,因此,如 果实例化的共享对象长时间不被利用,系统会认为它是垃圾,会自动销毁并回收资源,下次 利用时又将重新实例化,这将导致共享的单例对象状态的丢失。 3.适用场景 在以下情况下可以考虑使用单例模式: (1) 系统只需要一个实例对象,如系统要求提供一个唯一的序列号生成器或资源管理器,或者 需要考虑资源消耗太大而只允许创建一个对象。 (2) 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途 径访问该实例。
package com.myzy.auth.designpatterns;public class TestSingleTon { static class SingleTon { //私有构造方法 private SingleTon() { } private static volatile SingleTon singleTon = null; /** * 假如在某一瞬间线程A和线程B都在调用getInstance()方法,此时instance对象为null值,均能通 过instance == null的判断。 * 由于实现了synchronized加锁机制,线程A进入synchronized锁定的代 码中执行实例创建代码,线程B处于排队等待状态,必须等待线程A执行完毕后才可以进入 synchronized锁定代码。 * 但当A执行完毕时,线程B并不知道实例已经创建,将继续创建新的实 例,导致产生多个单例对象,违背单例模式的设计思想,因此需要进行进一步改进, * 在 synchronized中再进行一次(instance == null)判断,这种方式称为双重检查锁定(Double-Check Locking)。 * 使用双重检查锁定实现的懒汉式单例类完整代码如下所示 * @return */ private static SingleTon getInstance() { if (singleTon == null) { synchronized (SingleTon.class) { if (singleTon == null) { singleTon = new SingleTon(); } } } return singleTon; } /** * 需要注意的是,如果使用双重检查锁定来实现懒汉式单例类,需要在静态成员变量instance之 前增加修饰符volatile,被volatile修饰的成员变量可以确保多个线程都能够正确处理, * 且该代 码只能在JDK 1.5及以上版本中才能正确执行。由于volatile关键字会屏蔽Java虚拟机所做的一 些代码优化,可能会导致系统运行效率降低, * 因此即使使用双重检查锁定来实现单例模式也 不是一种完美的实现方式。 */ }}
|