本文的设计模式来源于github上人气比较高的iluwatar/java-design-patterns,包含了23种经典设计模式和很多实际应用中涉及到的模式。
文中涉及到的示例代码可能只抽取了部分进行讲解,如果有本地模拟需求,请参考源码。
“设计模式是程序员在设计应用程序时能够解决场景问题的最佳实现,通过经测试和验证的开发范例,可以提高开发效率。重用设计模式,可有效避免可能因细微问题而导致的重大隐患,同时有助于提升熟悉设计模式的编码人员和架构师对代码的可读性。”
作用
单例模式(Singleton),保证了一个类只会存在一个支持全局访问的实例。
适用性
以下场景下可以考虑使用单例模式:
- 一个类需要保证只有一个实例,同时这个实例需要为其他调用者提供统一的调用方式,如getInstance;
- 当一个实例需要通过子类进行扩展时,其调用者能够直接使用扩展后的实例而不用修改代码;
典型用例
- 日志记录类
- 数据库连接管理
- 文件管理器
代码示例
本文提供常见的几种实现方式,均属于线程安全的。
饿汉式
不论该对象会不会被使用,均进行实例化。缺陷:对于系统中不会被使用的单例,造成了一定的内存浪费。
1 2 3 4 5 6 7 8
| public final class IvoryTower { private IvoryTower() { } private static final IvoryTower INSTANCE = new IvoryTower(); public static IvoryTower getInstance() { return INSTANCE; } }
|
懒汉式
首次调用时才进行实例化。缺陷:每次调用均需要检查线程同步,一定程度上降低了性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public final class ThreadSafeLazyLoadedIvoryTower { private static ThreadSafeLazyLoadedIvoryTower instance; private ThreadSafeLazyLoadedIvoryTower() { if (instance == null) { instance = this; } else { throw new IllegalStateException("Already initialized."); } } public static synchronized ThreadSafeLazyLoadedIvoryTower getInstance() { if (instance == null) { instance = new ThreadSafeLazyLoadedIvoryTower(); } return instance; } }
|
静态内部类实例化
通过静态内部类完成实例化过程,保证在首次调用时才进行实例化的同时也属于线程安全的。
1 2 3 4 5 6 7 8 9 10 11
| public final class InitOnDemandHolderIdiom { private InitOnDemandHolderIdiom() { } public static InitOnDemandHolderIdiom getInstance() { return HelperHolder.INSTANCE; } private static class HelperHolder { private static final InitOnDemandHolderIdiom INSTANCE = new InitOnDemandHolderIdiom(); } }
|
双重检查锁
引用类如果为空时才进行线程同步判断,解决了懒汉式的多余线程同步判断问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public final class ThreadSafeDoubleCheckLocking { private static volatile ThreadSafeDoubleCheckLocking instance; private ThreadSafeDoubleCheckLocking() { if (instance != null) { throw new IllegalStateException("Already initialized."); } } public static ThreadSafeDoubleCheckLocking getInstance() { ThreadSafeDoubleCheckLocking result = instance; if (result == null) { synchronized (ThreadSafeDoubleCheckLocking.class) { result = instance; if (result == null) { instance = result = new ThreadSafeDoubleCheckLocking(); } } } return result; } }
|
枚举实现
枚举中定义方法,要求枚举构造函数必须是私有化的,同时枚举实例一定是static final的,因此可利用这些特性实现单例。该方式实际使用的没有前三种多,但是不失为一个更简洁的单例实现方式。
1 2 3 4 5 6 7
| public enum EnumIvoryTower { INSTANCE; @Override public String toString() { return getDeclaringClass().getCanonicalName() + "@" + hashCode(); } }
|
类图