单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
Implementation
懒汉式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package cn.leithda.single;
public class Singleton { private static Singleton instance;
private Singleton(){}
public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
|
懒汉式2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package cn.leithda.single;
public class Singleton2 { private static Singleton2 instance;
private Singleton2() { }
public static synchronized Singleton2 getInstance() { if (instance == null) { instance = new Singleton2(); } return instance; } }
|
饿汉式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package cn.leithda.single;
public class Singleton3 {
private static Singleton3 instance = new Singleton3();
private Singleton3(){}
public static Singleton3 getInstance(){ return instance; } }
|
双重锁验锁
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package cn.leithda.single;
public class Singleton4 {
private volatile static Singleton4 instance;
private Singleton4(){}
public static Singleton4 getInstance(){ if(instance == null){ synchronized (Singleton4.class){ if(instance == null){ instance = new Singleton4(); } } } return instance; } }
|
内部类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package cn.leithda.single;
public class Singleton5 {
private static class SingleHolder{ private static final Singleton5 INSTANCE = new Singleton5(); } private Singleton5(){}
public static Singleton5 getInstance(){ return SingleHolder.INSTANCE; } }
|
枚举方式
1 2 3 4 5 6 7 8 9 10 11 12 13
| package cn.leithda.single;
public enum Singleton6 { INSTANCE; }
|
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| package cn.leithda.single;
import org.junit.Test;
public class SingleTest {
@Test public void test() { Singleton singletonFirst = Singleton.getInstance(); Singleton singletonSecond = Singleton.getInstance(); System.out.println("singleton==singleton1 is " + (singletonFirst == singletonSecond));
Singleton2 singleton2First = Singleton2.getInstance(); Singleton2 singleton2Second = Singleton2.getInstance(); System.out.println("singleton2First==singleton2Second is " + (singleton2First == singleton2Second));
Singleton3 singleton3First = Singleton3.getInstance(); Singleton3 singleton3Second = Singleton3.getInstance(); System.out.println("singleton3First==singleton3Second is " + (singleton3First == singleton3Second));
Singleton4 singleton4First = Singleton4.getInstance(); Singleton4 singleton4Second = Singleton4.getInstance(); System.out.println("singleton4First==singleton4Second is " + (singleton4First == singleton4Second));
Singleton5 singleton5First = Singleton5.getInstance(); Singleton5 singleton5Second = Singleton5.getInstance(); System.out.println("singleton5First==singleton5Second is " + (singleton5First == singleton5Second));
Singleton6 singleton6First = Singleton6.INSTANCE; Singleton6 singleton6Second = Singleton6.INSTANCE; System.out.println("singleton6First==singleton6Second is " + (singleton6First == singleton6Second)); } }
|
- 关于反射调用示例私有构造方法的例子可以自行测试,可以通过Singleton中方式避免反射执行私有构造函数。
Usage
- 某些情况下,某个类要求只有一个实例的情况下
- 对象需要被共享时,使用单例可以节约内存空间,加快访问速度。如Web中的配置对象、数据库连接池等
- 当某个类需要频繁实例化,而创建的对象有频繁被销毁的情况下。如多线程的线程池、网络连接池等
- 各种 配置类 XxxManager 及 工厂类 XxxFactory