2.1 定义与特点

定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。
特点:

  1. 单例类只有一个实例对象;
  2. 该单例对象必须由单例类自行创建;
  3. 单例类对外提供一个访问该单例的全局访问点。

2.2 优点与缺点

优点:

  • 单例模式可以保证内存中只有一个实例,减少内存的开销;
  • 可以避免对资源的多重占用;
  • 单例模式设置全局访问点,可以优化和共享资源的访问。

缺点:

  • 单例模式一般没有接口,扩展困难。如要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则;
  • 在并发测试中,单例模式不利于代码调试。
  • 单例模式的功能代码通常写在一个类中,如果功能设计不合理,则很容易违背单一职责原则。

2.3 适用场景

  • 需要频繁的创建的一些类,使用单例可以降低系统的内存压力,减少GC;
  • 某类只要求生成一个对象的时候,如一个班中的班长、每个人的身份证号码等;
  • 某类创建实例时占用资源较多,或实例化耗时较长,且经常使用;
  • 某类需要频繁实例化,而且创建的对象又频繁被销毁的时候,如多线程的线程池、网络连接池等;
  • 频繁访问数据库或文件的对象;
  • 当对象需要被共享的场合。如Web中的配置的象、数据库连接池等。

2.4 单例模式的实现

单例模式的实现有两种形式:懒汉式与饿汉式
(1)懒汉式:类在加载时没有生产单例对象,而是在第一次调用getInstance方法时才去创建这个单例对象。

  1. public class LazySingleton {
  2. /**
  3. * volatile:保证共享对象在多线程环境下的可见性
  4. */
  5. private static volatile LazySingleton lazySingleton = null;
  6. /**
  7. * 构造私有化,避免外部被实例
  8. */
  9. private LazySingleton() {}
  10. /**
  11. * 增加同步控制
  12. * @return
  13. */
  14. public static synchronized LazySingleton getInstance() {
  15. if (lazySingleton == null) {
  16. lazySingleton = new LazySingleton();
  17. }
  18. return lazySingleton;
  19. }
  20. }

(2)饿汉式:类一旦加载,就创建单例对象。

  1. public class HungrySingleton {
  2. private static final HungrySingleton hungrySingleton = new HungrySingleton();
  3. private HungrySingleton(){}
  4. public static HungrySingleton getInstance(){
  5. return hungrySingleton;
  6. }
  7. }

注意:值得一提的是懒汉式与饿汉式在多线程环境下还是存在这很大的区别,懒汉式在并发时,每次访问都要进行同步控制,会影响性能,消耗资源。而饿汉式在类加载时就创建好了一个静态的实例,以后不会再改变,可以直接用于多线程环境而不会出现问题。