单例模式的实现

文章目录

C++ 实现

  • c++ 实现单例,并返回 单例的 shared_ptr 持有:
class Singleton
{
public:
    Singleton(Singleton const&) = delete; // 删除拷贝构造函数
    Singleton& operator=(Singleton const&) = delete; // 删除赋值

    static std::shared_ptr<Singleton> instance()
    {
        static std::shared_ptr<Singleton> s{new Singleton};
        //         static std::shared_ptr<Singleton> s{new Singleton,[] (Singleton* p) { delete p; }}; 这种写法会自定义一个析构回掉

        return s;
    }

    std::string getStrVal(){
        return "hello singleton";
    }

private:
    Singleton() {}
};

上面的写法中 是 Single const & ,有一个疑问就是 const Class& and Class const& 这两种写法有区别吗?

答案是没有区别。都表示对一个类的实例的引用
https://stackoverflow.com/questions/35153124/any-difference-between-const-class-and-class-const

Java 实现

  • 双重检查锁
    这种方式是一种懒汉模式,使用的时候再加载,节约了内存,同时使用volatile 关键字防止了指令重排,(如果不加volatile)可能Singleton的初始化操作和返回操作的指令进行了重排,返回后才进行初始化,这个时候另一个线程如果调用了该对象,就会出问题。

    class Singleton{
           private volatile static Singleton instance = null; 
           private Singleton() {
        
           }
           public static Singleton getInstance() {
               if(instance==null) {
                   synchronized (Singleton.class) {
                       if(instance==null)
                           instance = new Singleton();
                   }
               }
               return instance;
           } }

参考:双重校验锁中为什么要使用volatile关键字

  • 懒汉式
class Singleton {
    private static Singleton sSingleton;

    private Singleton() {
    }

    private static synchronized Singleton getInstance() {
        if (sSingleton == null) {
            sSingleton = new Singleton();
        }
        return sSingleton;
    }
}

该方式实现了懒加载,但是getInstance()方法需要加synchronized锁,影响效率。

  • 饿汉式
class Singleton {
    private Singleton() {
    }

    private static Singleton singleton = new Singleton();

    private static Singleton getInstance() {
        return singleton;
    }
}

该方式使用classloader初始化加载机制避免了多线程初始化对象,但是instance在类加载的时候就会初始化,没有做到懒加载。

  • 静态内部类
public class Singleton {  
    private static class SingletonHolder {  
    private static final Singleton INSTANCE = new Singleton();  
    }  
    private Singleton (){}  
    public static final Singleton getInstance() {  
    return SingletonHolder.INSTANCE;  
    }  
}

使用Classloader机制保证了初始化instance时只有一个线程,同时只有在使用SingleHolder类的时候才会去主动创建实例,做到了懒加载。

  • 使用枚举
class Resource{
}
public enum SomeThing {
    INSTANCE;
    private Resource instance;
    SomeThing() {
        instance = new Resource();
    }
    public Resource getInstance() {
        return instance;
    }
}

INSTANCE对象会在类加载的时候创建,并且还自动支持序列化机制,防止反序列化重新创建新的对象。

  • 抽象类实现单例模式

自己在看android源码的时候看到了一种抽象类实现单例的方式,这里进行记录

源码位置;
android.util.Singleton
/**
 * Singleton helper class for lazily initialization.
 */
public abstract class Singleton<T> {

    public Singleton() {
    }

    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

上面定义了一个抽象类,抽象类中有抽象方法create,get获取单例的时候会调用抽象方法创建我们需要的单例对象,从而实现了懒加载,自己理解上面的if判断也可以换成双重教研锁,这样能更好点。
使用方式:

class Resource {
    static {
        System.out.println("resource init");
    }
}
    private Singleton<Resource> mResource = new Singleton<Resource>() {
        @Override
        protected Resource create() {
            return new Resource();
        }
    };

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值