设计模式入门:单例模式

2021-09-10 18:01:35 浏览数 (1)

### UML类图

![单例模式](http://upload-images.jianshu.io/upload_images/9709135-eba21220b6f018cd.jpg?imageMogr2/auto-orient/strip|imageView2/2/w/1240)

### 代码示例

1. 饿汉式

``` java

/**

* 单例模式:饿汉式

* <p>

* a.线程安全

* b.提前初始化(占用资源)

* c.类加载慢但获取对象快

*/

public class HungrySingleton {

private static final HungrySingleton INSTANCE = new HungrySingleton();

/**

* 私有构造器

*/

private HungrySingleton() {

}

/**

* 获取当前实例的唯一入口

*

* @return 当前实例

*/

public static HungrySingleton getInstance() {

return INSTANCE;

}

}

```

2.1 懒汉式

``` java

/**

* 单例模式:懒汉式

* <p>

* a.非线程安全

* b.实现延迟加载

* c.类加载快但获取对象慢

*/

public class LazySingleton {

private static LazySingleton instance = null;

/**

* 私有构造器

*/

private LazySingleton() {

}

/**

* 获取当前实例的唯一入口

* 多线程下非线程安全

*

* @return 当前实例

*/

public static LazySingleton getInstance() {

if (instance == null) {

instance = new LazySingleton();

}

return instance;

}

}

```

2.2 懒汉式(同步锁synchronized)

``` java

/**

* 单例模式:懒汉式(synchronized)

* <p>

* a.非线程安全

* b.实现延迟加载

* c.类加载快但获取对象慢

*/

public class SynchronizedSingleton {

private static SynchronizedSingleton instance = null;

/**

* 私有构造器

*/

private SynchronizedSingleton() {

}

/**

* 获取当前实例的唯一入口

* 通过synchronized机制保证多线程安全,但同时也消耗较多的性能

*

* @return 当前实例

*/

public static synchronized SynchronizedSingleton getInstance() {

if (instance == null) {

instance = new SynchronizedSingleton();

}

return instance;

}

}

```

2.3 懒汉式(DCL)

``` java

/**

* 单例模式:懒汉式(双重检测锁。DCL , Double-checked Locking)

* <p>

* a.非线程安全

* b.实现延迟加载

* c.类加载快但获取对象慢

*/

public class DCLSingleton {

/**

* volatile确保了实例的可视性

*/

private static volatile DCLSingleton instance = null;

/**

* 私有构造器

*/

private DCLSingleton() {

}

/**

* 获取当前实例的唯一入口

* 通过DCL机制保证多线程安全,同时消耗较少的性能

*

* @return 当前实例

*/

public static DCLSingleton getInstance() {

if (instance == null) {

synchronized (DCLSingleton.class) {

if (instance == null) {

instance = new DCLSingleton();

}

}

}

return instance;

}

}

```

3. 静态内部类

``` java

/**

* 单例模式:登记式(静态内部类)

* <p>

* a.线程安全

* b.实现延迟加载

*/

public class InnerClassSingleton {

/**

* 静态内部类,用于初始化调用时实例化当前 instance

*/

private static class InnerStaticClassHolder {

private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();

}

/**

* 私有构造器

*/

private InnerClassSingleton() {

}

/**

* 获取当前实例的唯一入口

* 通过对静态域使用延迟初始化达到延迟加载的效果

* (只有通过显式调用 getInstance 方法时,才会显式装载 InnerStaticClassHolder 类,从而实例化 instance)

*

* @return 当前实例

*/

private static InnerClassSingleton getInstance() {

return InnerStaticClassHolder.INSTANCE;

}

}

```

4. 枚举

``` java

/**

* 单例模式:枚举

* <p>

* a.线程安全

* b.非延迟加载

* c.代码更简洁,支持序列化机制

* ps: 这是实现单例模式的最佳方式,但未被广泛使用。

*/

public enum EnumSingleton {

/**

* 该定义用于返回当前实例

*/

INSTANCE;

}

```

### 总结思考

&emsp;&emsp;单例模式属于创建型模式,是一种较为简单的设计模式,但也是最容易让人犯错的。在不同的单例模式实现中,首先要确保构造函数是私有的,然后提供一个静态入口(方法)用于获取唯一的实例。

&emsp;&emsp;大多数情况下,不建议使用非线程安全的以及synchronized监视器锁实现的懒汉方式,在资源允许的情况下尽可能使用饿汉模式。如果明确要实现 lazy loading 效果时,可以使用静态内部类形式。如果涉及到反序列化创建对象时,可以尝试使用枚举方式。如果有其他特殊的需求,可以考虑使用DCL双检锁的方式。

> [示例代码](https://github.com/happyjared/java-learning/tree/master/design-patterns)

0 人点赞