六个创建模式之单例模式(Singleton Pattern)

定义:
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。三个特点:一个类只有一个实例;必需自己创建这个实例;必需自行向整个系统提供这个实例。

结构图:

  • Singleton:单例类,提供一个静态的getInstance()方法,供系统获取它的唯一实例;构造函数需要私有化;内部定义自身的一个静态变量,作为外部共享的唯一实例。

**Hungry Mode **
为了保证创建实例时的线程安全,可以使用Hungry Mode的方式初始化实例。

class EagerSingleton {   
    private static final EagerSingleton instance = new EagerSingleton();   
    private EagerSingleton() { }   

    public static EagerSingleton getInstance() {  
        return instance;   
    }     
}
  • 在类的初始化的时候就直接创建实例,无需考虑多线程访问的问题,但无论系统是否需要改单例,都需要进行实例化。如果实例化复杂,则类加载时间较长,浪费系统资源。

Lazy Mode
为了解决初始化问题,可以在系统第一次调用的时候再生成实例。

class LazySingleton {   
    private static LazySingleton instance = null;   

    private LazySingleton() { }   

    synchronized public static LazySingleton getInstance() {   
        if (instance == null) {  
            instance = new LazySingleton();   
        }  
        return instance;   
    }  
}
  • 在整个getInstance()方法上面加锁可以保证线程安全,但是因为只有在第一次初始化会出现不同步的问题,如果后面所有操作都要进行加锁操作,则系统性能大幅下降。
  • 如果采用双重检查锁,在一定条件下也会失效,详细参考《Java 并发编程艺术》。

Initialization Demand Holder(IoDH)
在需要实例化的单例类内引入一个静态内部类,当一次初始化实例时,由类加载器保证线程安全。既可以保证延迟加载,有可以保证线程安全,而且不影响系统性能。

//Initialization on Demand Holder  
class Singleton {  
    private Singleton() {  
    }  

    private static class HolderClass {  
            private final static Singleton instance = new Singleton();  
    }  

    public static Singleton getInstance() {  
        return HolderClass.instance;  
    }   
}

优点:

  • 提供了对唯一实例的受控访问,用户不能实例化单例类。
  • 节省系统资源,适用于一些频繁创建和销毁的对象。

缺点:

  • 没有定义抽象层,很难进行扩展。
  • 单例类职责过多,将单例的创建和本身功能融合在一起,一定程度上违反了“单一职责原则”。

适用场景:

  • 系统只需要一个实例对象,如序列生成器,资源管理器等。
  • 客户调用类的单个实例只允许使用一个公共访问点,除了该公共访问点,不能通过其他途径访问该实例。

实例:
SingletonPattern.java

posted on 2016-10-25 10:24  云破天蓝  阅读(162)  评论(0编辑  收藏  举报

导航