前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >设计模式之——Singleton pattern

设计模式之——Singleton pattern

作者头像
Yano_nankai
发布2018-10-08 10:49:13
4240
发布2018-10-08 10:49:13
举报
文章被收录于专栏:二进制文集二进制文集

单例模式网址

Singleton pattern - wikipedia

单例模式定义

在一个系统中,一个类只有一个实例化的对象。

单例模式应用

  • The abstract factory, builder, and prototype patterns can use Singletons in their implementation.
  • Facade objects are often singletons because only one Facade object is required.
  • State objects are often singletons.
  • Singletons are often preferred to global variables because:
    • They do not pollute the global namespace (or, in languages with namespaces, their containing namespace) with unnecessary variables.<sup id="cite_ref-4" class="reference" style="line-height: 1; unicode-bidi: -webkit-isolate; white-space: nowrap; font-size: 12px; font-weight: normal; font-style: normal;">
    • They permit lazy allocation and initialization, whereas global variables in many languages will always consume resources.

实现方案

The singleton pattern is implemented by creating a class with a method that creates a new instance of the class if one does not exist. If an instance already exists, it simply returns a reference to that object.

可以实现延迟加载,即使用之前不占用内存或资源。(Note the distinction between a simple static instance of a class and a singleton: although a singleton can be implemented as a static instance, it can also be lazily constructed, requiring no memory or resources until needed.)

The singleton pattern must be carefully constructed in multi-threaded applications. If two threads are to execute the creation method at the same time when a singleton does not yet exist, they both must check for an instance of the singleton and then only one should create the new one. If the programming language has concurrent processing capabilities the method should be constructed to execute as a mutually exclusive operation. The classic solution to this problem is to use mutual exclusion on the class that indicates that the object is being instantiated.

Lazy initialization

使用“双重检查加锁”——double-checked locking。其中变量 instance 是 volatile 的,1.4及更早的Java中,volatile关键字的实现会导致双重检查加锁的失效。具体原因,参考 The "Double-Checked Locking is Broken" Declaration

代码语言:javascript
复制
public final class SingletonDemo {
    private static volatile SingletonDemo instance;
    private SingletonDemo() { }

    public static SingletonDemo getInstance() {
        if (instance == null ) {
            synchronized (SingletonDemo.class) {
                if (instance == null) {
                    instance = new SingletonDemo();
                }
            }
        }

        return instance;
    }
}

在并发性并不是很高,性能并不特别需求的情况下,可以使用下面简洁的方法:

代码语言:javascript
复制
public final class SingletonDemo {
    private static SingletonDemo instance = null;
    private SingletonDemo() { }

    public static synchronized SingletonDemo getInstance() {
        if (instance == null) {
            instance = new SingletonDemo();
        }

        return instance;
    }
}

Eager initialization

如果系统总是需要一个实例,或者创建实例的开销并不大,可以使用Eager initialization,它总是返回一个实例。

代码语言:javascript
复制
public final class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

这种方法的好处:

  1. 在类加载之后、被任何线程使用之前,static 的变量 INSTANCE 就已经定义好。
  2. 方法getInstance()不需要同步,所有的线程都会看到同样的实例。
  3. 关键字final使得 INSTANCE 不能修改,保证有且只有一个实例。

Static block initialization

static代码块中创建新实例,同Eager initialization

代码语言:javascript
复制
public final class Singleton {
    private static final Singleton instance;

    static {
        try {
            instance = new Singleton();
        } catch (Exception e) {
            throw new RuntimeException("Darn, an error occurred!", e);
        }
    }

    public static Singleton getInstance() {
        return instance;
    }

    private Singleton() {
        // ...
    }
}

Initialization-on-demand holder idiom

  1. 尽可能延迟加载
  2. 适用于所有的 Java 版本
  3. 线程安全
代码语言:javascript
复制
public final class Singleton {
        // Private constructor. Prevents instantiation from other classes.
        private Singleton() { }

        private static class SingletonHolder {
                private static final Singleton INSTANCE = new Singleton();
        }

        public static Singleton getInstance() {
                return SingletonHolder.INSTANCE;
        }
}

内部类SingletonHolder在方法getInstance()被调用时,才会被 class loader 加载。因此这个方法是线程安全的,不需要额外的同步手段。内部类SingletonHolder也可以被定义成final的。

The enum way

In the second edition of his book Effective Java, Joshua Bloch claims that "a single-element enum type is the best way to implement a singleton" for any language that supports enums, like Java.

代码语言:javascript
复制
public enum Singleton {
    INSTANCE;
    public void execute (String arg) {
        // Perform operation here 
    }
}

Java语言保证,枚举类型会在需要使用时,通过 class loader 加载。同时 Java 的枚举类型是全局可见的,但是有些呆板 0_o。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016.07.20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单例模式网址
  • 单例模式定义
  • 单例模式应用
  • 实现方案
    • Lazy initialization
      • Eager initialization
        • Static block initialization
          • Initialization-on-demand holder idiom
            • The enum way
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档