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