单例设计模式 (Singleton)
描述: 一个类有且仅有一个实例的类
特点: 单例类只有一个实例,单例必须自己创建自己的唯一实例,必须给其他的访问对象提供自己的试列 。这样的好处就是避免了内存的频繁的创建和销毁实例。
饿汉式
1 2 3 4 5 6 7 8 9 10 11 12 13
|
class Test{ private Test(){} private static final Test t = new Test();
public static Test getTest(){ return t; } }
|
懒汉式(线程不安全)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
class Test { private static Test t = null;
private Test() { }
public static Test getTest() { if (t == null) { t = new Test(); } return t; } }
|
懒汉式/双重检查机制(线程安全的 DCL)
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
|
class Test { private volatile static Test t = null; private Test() { }
public static Test getTest() { if (t == null) { synchronized (Test.class) { if(t== null){ t = new Test(); } } } return t; } }
|
静态内部类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
class Test { private Test() { } private static class Test1{ private final static Test t1 = new Test(); } public static Test getTest() { return Test1.t1; } }
|
基于枚举单列模式(推荐使用)
注意: 其中只有枚举方式的单例不会被破坏,其他都能够使用反射或者序列化的方式破坏单例
实例: 使用反射破坏单例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class test5 { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Test test = Test.getTest(); Constructor<Test> constructor = Test.class.getDeclaredConstructor(); constructor.setAccessible(true); Test t1 = constructor.newInstance(); System.out.println(test.equals(t1)); }
}
|
避免反射破坏
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Test{ private static final Test t = new Test(); private Test(){ if(t != null){ throw new RuntimeException("请使用getSingleton()方法获取单例对象"); } }
public static Test getTest(){ return t; } }
|
使用序列化破坏(须实现序列化接口 Serializable)
1 2 3 4 5 6
| public static void main(String[] args) { Singleton instance = Singleton.getInstance(); byte[] serialize = SerializationUtils.serialize(instance); Singleton newInstance = SerializationUtils.deserialize(serialize); System.out.println(instance == newInstance); }
|
避免反序列化破坏 就是不实现反序列化接口