1. 抛出问题, 先代码实现(非设计模式方式)
2. 具体设计模式说明和解释(生活应用场景)
项目中读取文件的类, 做数据库连接的类
3. 代码实现
饿汉式 :个人推荐, 简单, 安全.
这种方式可以保证线程安全(因为类加载时, 直接创建了实例, JVM 可以保证这个实例是线程安全的, 所以getInstance不需要synchronized)
package com.leon.design; public class SingletonDemo { public static void main(String[] args) { SingletonHungry s1 = SingletonHungry.getInstance(); SingletonHungry s2 = SingletonHungry.getInstance(); System.out.println(s1.equals(s2)); } } class SingletonHungry { private static SingletonHungry instance = new SingletonHungry(); private SingletonHungry() {}; public static SingletonHungry getInstance() { return instance; } }
懒汉式 : 不推荐
package com.leon.design; import java.lang.reflect.Constructor; public class SingletonDemo2 { public static void main(String[] args) throws Exception { SingletonLazy s1 = SingletonLazy.getInstance(); SingletonLazy s2 = SingletonLazy.getInstance(); System.out.println(s1.equals(s2)); } } class SingletonLazy { private static SingletonLazy instance; private SingletonLazy() {}; public static synchronized SingletonLazy getInstance() { if (instance == null) { instance = new SingletonLazy(); } return instance; } }
静态内部类: 类似饿汉式
package com.leon.design; import java.lang.reflect.Constructor; public class SingletonDemo3 { public static void main(String[] args) throws Exception { SingletonLazy s1 = SingletonLazy.getInstance(); SingletonLazy s2 = SingletonLazy.getInstance(); System.out.println(s1.equals(s2)); } } class SingletonStatic { // 内部类加载(也相当于类加载时) 创建的对象, 所以是线程安全的 private static class SingletonStaticInner { private static final SingletonStatic instance = new SingletonStatic(); } public static SingletonStatic getInstance() { return SingletonStaticInner.instance; } private SingletonStatic() {}; }
枚举:
package com.leon.design; import java.lang.reflect.Constructor; public class SingletonDemo4 { public static void main(String[] args) throws Exception { SingletonEnum s1 = SingletonEnum.INSTANCE; SingletonEnum s2 = SingletonEnum.INSTANCE; System.out.println(s1.equals(s2)); s1.otherFunction(); } } // 因为枚举本事是单例的, 所以可以直接使用 INSTANCE enum SingletonEnum { INSTANCE; public void otherFunction() { System.out.println("others"); }; }
4. UML图 (原理与角色)
5. 具体源码应用 & 分析
JDK 中的 RUNTime 类 -> 用的是 饿汉式 方式.
应用场景:
需要频繁进行创建 / 销毁的对象
创建对象时消耗过多的资源, 但又经常用到的对象,工具类对象,频繁访问数据库/文件的对象.