单例模式(Singleton Pattern)是一种设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。单例模式常用于需要全局唯一对象的场景,如配置管理器、日志记录器、线程池等。
单例模式的实现步骤
- 私有化构造方法:防止外部类通过构造方法创建实例。
- 创建一个私有的静态变量:用于保存类的唯一实例。
- 提供一个公共的静态方法:用于返回类的唯一实例。
单例模式的实现示例
我们以一个简单的 Singleton
类为例,完整实现单例模式。
单例类 Singleton
public class Singleton {
// 私有的静态变量,保存唯一的实例
private static Singleton instance = null;
// 私有化构造方法,防止外部类创建实例
private Singleton() {
// 可以在此处初始化一些资源
}
// 公共的静态方法,返回唯一的实例
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// 一个示例方法
public void showMessage() {
System.out.println("Hello from Singleton!");
}
}
使用单例类
public class Main {
public static void main(String[] args) {
// 获取 Singleton 类的唯一实例
Singleton singleton1 = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
// 调用实例方法
singleton1.showMessage();
// 验证两个实例是否是同一个
System.out.println(singleton1 == singleton2); // true
}
}
实现流程
-
私有化构造方法:
private Singleton() {}
:防止外部类通过new
关键字创建Singleton
类的实例。
-
创建私有的静态变量:
private static Singleton instance = null;
:用于保存Singleton
类的唯一实例,初始值为null
。
-
提供公共的静态方法:
public static Singleton getInstance()
:检查instance
是否为null
。如果是,则创建一个新的Singleton
实例并赋值给instance
。否则,直接返回已有的实例。
输出结果
运行 Main
类的 main
方法,输出结果如下:
Hello from Singleton!
true
Hello from Singleton!
:这是调用singleton1.showMessage()
方法的输出,表明我们成功调用了Singleton
类的实例方法。true
:这是System.out.println(singleton1 == singleton2);
的输出,表明singleton1
和singleton2
是同一个实例。
线程安全的单例模式
上述实现并不是线程安全的。在多线程环境下,可能会创建多个实例。为了实现线程安全的单例模式,可以使用同步方法或者双重检查锁定。
使用同步方法
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
使用双重检查锁定
public class Singleton {
private static volatile Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
为什么能确保唯一实例?
private static Singleton instance = null;
1. 静态变量的特性
静态变量是属于类本身的,而不是类的某个实例。当一个类被加载时,其静态变量会被初始化,并且在整个程序运行期间都存在。由于静态变量在所有实例之间共享,因此它在类的所有实例中保持唯一性。
2. 私有访问权限
将变量声明为 private
确保了只有 Singleton
类内部的方法可以访问和修改这个变量。外部类无法直接访问或修改这个变量,从而保证了对该变量的控制,防止外部代码创建多个实例。
3. 控制实例创建的静态方法
通过提供一个公共的静态方法(如 getInstance()
),我们可以控制实例的创建和访问。这个方法检查静态变量 instance
是否为 null
,如果是,则创建一个新的实例;如果不是,则直接返回已有的实例。
4. 确保唯一性的逻辑
在 getInstance()
方法中,我们通过检查 instance
是否为 null
来确保只有一个实例被创建。
总结
单例模式确保一个类只有一个实例,并提供一个全局访问点。通过私有化构造方法、创建私有的静态变量和提供公共的静态方法,我们可以实现单例模式。在多线程环境下,可以使用同步方法或双重检查锁定来确保线程安全。