Java设计模式学习(一):单例模式

186 阅读3分钟

本篇开始学习设计模式。

设计模式

先说明一下什么是设计模式 ?

设计模式是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。

个人理解就是对于软件开发过程中遇到的一般性问题的比较标准的解决性方案,是前辈们在长期试错总结得到的经验。

希望以后可以逐个学习。本篇从单例模式开始。

单例模式

单例模式的定义:

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

这段定义要注意的有三点:

  1. 单例类只能有一个实例。
  2. 单例类必须自己创建自己的唯一实例。
  3. 单例类必须给所有其他对象提供这一实例。

实现方式

单例模式一般分为懒汉式和饿汉式。下面分别说明。

饿汉式

比较常用的一种方式,在类加载时就进行初始化操作,使用方便,就是比较浪费内存。这是一种线程安全的、支持多线程的、效率较高的方式。

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    
    public static Singleton getInstance() {  
    	return instance;  
    }  
}

2.懒汉式

顾名思义,在使用时加载才去初始化。

下面是基本的实现方式,这是一种线程不安全的、不支持多线程的 lazy loading 方式。

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
	    if (instance == null) {  
	        instance = new Singleton();  
	    }  
	    	return instance;  
	    }  
}

对于这种方式,如果多个线程同时调用 getInstance() 方法,进入 if 后,就会出现多个线程创建了多个 Singleton 的情况。

为了解决线程不安全不支持多线程的问题,我们可以通过加锁来处理,然后就有了下面的这种方法。

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){} 
     
    public static synchronized Singleton getInstance() {  
	    if (instance == null) {  
	        instance = new Singleton();  
	    }  
	    	return instance;  
	    }  
}

在方法名上加了锁,这样的话,就可以完美解决上面的问题!

但是,同时产生了新的问题。这样操作就会导致效率很低。每次都要锁。为了解决该问题,又出现了新的解决方案。

即 DCL(double checked locking)双重锁校验。

这种方式采用双重锁校验机制,保证了延迟加载、安全且在多线程情况下能保持高性能。

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    
    public static Singleton getSingleton() {  
	    if (singleton == null) {  
	        synchronized (Singleton.class) {  
		        if (singleton == null) {  
		            singleton = new Singleton();  
		        }  
	        }  
	    }  
	    return singleton;  
    }  
}

除了这些,还有枚举的方式比较推荐。

关于单例基本上就这些。

参考

单例模式完全详解
单例模式几种实现方式