Singleton——单例模式

什么是单例模式

  1. **_确保一个类只生成一个实例,并提供一个访问它的全局访问点_**。<br />
  2. Singleton模式让类负责保存它的唯一实例,这个类可以保证没有其他实例可以被创建,并且提供一个访问该实例的方法

单例模式的角色构成

  • Singleton
    Singleton角色中有一个返回唯一实例的静态方法,该方法总会返回同一个实例。

示例程序

类的组成表

类名 说明
Singleton 只生成一个实例
SingletonMain 测试类

示例程序类图

Singleton类

  1. Singleton类只会生成一个实例,Singleton类定义了一个静态成员变量singleton,在类被加载时会将singleton初始化为Singleton的实例,初始化行为仅在该类被加载时进行一次。<br />
  2. Singleton类的构造函数使用了private修饰,这是为了禁止从Singleton类外部调用构造函数。如果从Singleton类以外调用构造方法new Singleton(),会出现编译错误,getInstance()方法提供了获取Singleton类唯一实例的入口。
  1. package com.example.singleton;
  2. public class Singleton {
  3. private static Singleton singleton = new Singleton();
  4. private Singleton() {
  5. System.out.println("生成了一个实例");
  6. }
  7. public static Singleton getInstance() {
  8. return singleton;
  9. }
  10. }

SingletonMain类

  1. 调用两次getInstance()方法获取Singleton类的实例,通过"=="判断是否为同一个实例。
  1. package com.example.singleton;
  2. public class SingletonMain {
  3. public static void main(String[] args) {
  4. System.out.println("Start");
  5. Singleton obj1 = Singleton.getInstance();
  6. Singleton obj2 = Singleton.getInstance();
  7. if (obj1 == obj2) {
  8. System.out.println("obj1和obj2是相同的实例");
  9. } else {
  10. System.out.println("obj1和obj2是不同的实例");
  11. }
  12. System.out.println("End");
  13. }
  14. }

测试结果

  1. Start
  2. 生成了一个实例
  3. obj1obj2是相同的实例
  4. End

拓展延伸

多线程下的单例模式

在多线程环境下,以下程序在多个线程调用getInstance()方法创建实例时,可能会生成多个实例;

示例程序:

SingletonThread类
  1. package com.example.singleton.test;
  2. public class SingletonThread {
  3. private static SingletonThread singleton = null;
  4. private SingletonThread() {
  5. System.out.println("生成了一个实例");
  6. slowdown();
  7. }
  8. public static SingletonThread getInstance() {
  9. // 线程不安全,使用null == singleton判断实例为空后,生成了一个新的实例
  10. // 在多线程环境下,其他线程也可能判断 if (null == singleton)
  11. if (null == singleton) {
  12. singleton = new SingletonThread();
  13. }
  14. return singleton;
  15. }
  16. private void slowdown() {
  17. try {
  18. Thread.sleep(1000);
  19. } catch (InterruptedException e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. }

SingletonThreadMain类

  1. package com.example.singleton.test;
  2. public class SingletonThreadMain extends Thread{
  3. public static void main(String[] args) {
  4. System.out.println("Start.");
  5. new SingletonThreadMain("A").start();
  6. new SingletonThreadMain("B").start();
  7. new SingletonThreadMain("C").start();
  8. System.out.println("End.");
  9. }
  10. public void run() {
  11. SingletonThread obj = SingletonThread.getInstance();
  12. System.out.println(getName() + ": obj = " + obj);
  13. }
  14. public SingletonThreadMain(String name) {
  15. super(name);
  16. }
  17. }

测试结果
  1. Start.
  2. End.
  3. 生成了一个实例
  4. 生成了一个实例
  5. 生成了一个实例
  6. B: obj = com.example.singleton.test.SingletonThread@59e72e28
  7. C: obj = com.example.singleton.test.SingletonThread@4a140fe5
  8. A: obj = com.example.singleton.test.SingletonThread@2f5aff2b