设计模式单例模式——单例有几种写法?

Posted harrickheng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式单例模式——单例有几种写法?相关的知识,希望对你有一定的参考价值。

有一回对我说道,“你写过编程么?”我略略点一点头.他说,“写过,……我便考你一考.单例模式,是怎样写的?”我想,讨饭一样的人,也配考我么?便回过脸去,不再理会.孔乙己等了许久,很恳切的说道,“不能写罢?……我教给你,记着!

单例模式(Singleton Pattern)

单例模式是 Java 中最简单的设计模式之一。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

单例模式三要素:1.单例类只能有一个实例。 2.单例类必须自己创建自己的唯一实例。 3.单例类必须给所有其他对象提供这一实例。

技术图片

应用场景

1.游戏开发中的跟随主角视角的摄像头,一般只有一个

2.要求生产唯一序列号,用来防伪

3.WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来

4.创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等

 

单例模式的四种写法

虽然演示语言是typescript,最终以javascript实现,而js没有多线程,不用考虑线程安全问题。但笔者依然会列出其中的线程安全问题,ts不考虑,java、c还是要的。

懒汉模式

class SingleTest 
    private static instance: SingleTest;
    constructor() 

    

    public static getInstance(): SingleTest 
        if(this.instance == null) 
            this.instance = new SingleTest();
        return this.instance;
    

这是最基本的实现方式,为什么叫懒汉?因为要等别人调用了你才实例化对象,有够懒的。缺点很明显:不支持多线程。如果要保证线程安全,需要加锁synchronized,当然也会影响效率。

饿汉模式

class Singleton   
    private static instance:Singleton  = new Singleton();  
    constructor ()  
    public static getInstance(): Singleton   
    return this.instance;  
      

很常用的模式。为什么叫饿汉?因为类在装载的时候你就实例化了,别人还没上桌你就吃完了,饿死鬼投胎!容易写,而且执行效率会提高。缺点也很明显:类加载时就初始化,浪费内存,容易产生垃圾对象。

以下模式为多线程语言的设计模式,所以不用ts演示了。

双检锁/双重校验锁(DCL,即 double-checked locking)

public class Singleton   
    private volatile static Singleton singleton;  
    private Singleton ()  
    public static Singleton getSingleton()   
    if (singleton == null)   
        synchronized (Singleton.class)   
        if (singleton == null)   
            singleton = new Singleton();  
          
          
      
    return singleton;  
      

这种方式采用双锁机制,安全且在多线程情况下能保持高性能。

登记式/静态内部类

public class Singleton   
    private static class SingletonHolder   
    private static final Singleton INSTANCE = new Singleton();  
      
    private Singleton ()  
    public static final Singleton getInstance()   
    return SingletonHolder.INSTANCE;  
      

这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。

枚举

public enum Singleton   
    INSTANCE;  
    public void whateverMethod()   
      

实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。但是需要JDK1.5 之后加入的enum 特性才可使用。

 

孔乙己显出极高兴的样子,将两个指头的长指甲敲着柜台,点头说,“对呀对呀!……单例模式有四样写法,你知道么?

 

以上是关于设计模式单例模式——单例有几种写法?的主要内容,如果未能解决你的问题,请参考以下文章

再见面试官:单例模式有几种写法?

06期单例模式有几种写法?

面试中单例模式有几种写法?

孔乙己的疑问:单例模式有几种写法

面试问题:单例模式有几种写法?

单例模式有几种写法