设计模式之单例模式
单例:一个类只有一个实例。
实现方式:1.私有化类的对象 2.类的构造函数私有化 3.提供一个公共的方法获取类的对象
demo1:懒汉模式 (实现了lazy 加载 没有加锁 线程不安全)
public class Singleton01 { private static Singleton01 instance; private Singleton01() { } public static Singleton01 getInstance() { if (instance == null) { instance = new Singleton01(); } return instance; } }
demo2:饿汉模式(没有lazy加载 消耗内存)
public class Singleton02 { private static Singleton02 instance = new Singleton02(); private Singleton02() { } public static Singleton02 getInstance() { return instance; } }
demo3: 懒汉模式加锁(每次调用执行synchronized 效率低)
public class Singleton03 { private static Singleton03 instance; private Singleton03() { } public static synchronized Singleton03 getInstance() { if (instance == null) { instance = new Singleton03(); } return instance; } }
demo4: 双检锁实现
public class Singleton04 { private static Singleton04 instance; private Singleton04() { } private static Singleton04 getInstance() { if (instance == null) { synchronized (Singleton04.class) { if (instance == null) { instance = new Singleton04(); } } } return instance; } }
demo5:静态内部类实现 静态内部类在调用的时候才初始化,静态属性只初始化一次
public class Singleton05 { private static class SingletonHolder { private static final Singleton05 INSTANCE = new Singleton05(); } private Singleton05() { } public static Singleton05 getInstance() { return SingletonHolder.INSTANCE; } }
demo6: emun枚举实现
public enum Singleton06 { INSTANCE; }
单例模式可以破坏吗? 可以
方式一:通过反射破坏单例类
public class ReflectSingleton { public static void main(String[] args) throws Exception { Class clazz = Class.forName("com.wl.demo.demos.singleton.Singleton01"); Constructor constructor = clazz.getDeclaredConstructor(); constructor.setAccessible(true); Singleton01 s1 = (Singleton01) constructor.newInstance(); Singleton01 s2 = (Singleton01) constructor.newInstance(); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println(s1.equals(s2)); } }
解决办法:构造函数抛出异常:
private Singleton01() { if (instance != null) { throw new RuntimeException(); } }
方式二:序列化破坏单例
public class BreakSingleton { public static void main(String[] args) throws IOException, ClassNotFoundException { Singleton01 s1 = Singleton01.getInstance(); Singleton01 s2 = Singleton01.getInstance(); System.out.println(s1 == s2); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\file\\test.txt")); oos.writeObject(s1); oos.close(); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\file\\test.txt")); Singleton01 s3 = (Singleton01) ois.readObject(); System.out.println(s1.hashCode()); System.out.println(s2.hashCode()); System.out.println(s3.hashCode()); System.out.println(s1 == s3); } }
解决办法:
//反序列化定义该方法,则不需要创建新对象 private Object readResolve() throws ObjectStreamException { return instance; }