【设计模式】手写一下单例模式?(约279字)

单例模式

保证一个类仅有一个实例,并提供一个该实例的全局访问点

版本一

C++

class Singleton1 {
public:
    static Singleton1* GetInstance() {
        if (instance == nullptr) {
            instance = new Singleton1();
        }
        return instance;
    }
private:
    // 防止外界构造和删除对象
    Singleton1() = default;
    ~Singleton1() = default;
    Singleton1(const Singleton1&) = default;
    Singleton1& operator=(const Singleton1&) = default;

    static Singleton1 *instance;
};

Singleton1* Singleton1::instance = nullptr;

存在内存泄露问题,instance是在堆上的,需要手动释放,但是外界没办法调用delete释放对象

线程安全问题,可能会有多个线程同时分配内存

版本二

C++

class Singleton2 {
public:
    static Singleton2* GetInstance() {
        if (instance == nullptr) {
            instance = new Singleton2();
            atexit(Destructor); // 在程序退出的时候释放
        }
        return instance;
    }
private:
    // 防止外界构造和删除对象
    Singleton2() = default;
    ~Singleton2() = default;
    Singleton2(const Singleton2&) = default;
    Singleton2& operator=(const Singleton2&) = default;

    static void Destructor() {
        if (instance != nullptr) {
            delete instance;
            instance = nullptr;
        }
    }

    static Singleton2 *instance;
};

Singleton2* Singleton2::instance = nullptr;

解决了内存泄露问题

版本三

C++

class Singleton3 {
public:
    static Singleton3* GetInstance() {
        if (instance == nullptr) {
            lock_guard lock(mutex_);
            if (instance == nullptr) {
                instance = new Singleton3();
                atexit(Destructor);
            }
        }
        return instance;
    }
private:
    // 防止外界构造和删除对象
    Singleton3() = default;
    ~Singleton3() = default;
    Singleton3(const Singleton3&) = default;
    Singleton3& operator=(const Singleton3&) = default;

    static void Destructor() {
        if (instance != nullptr) {
            delete instance;
            instance = nullptr;
        }
    }

    static Singleton3 *instance;
    static mutex mutex_;
};

Singleton3* Singleton3::instance = nullptr;

new的时候的操作分为三步:分配内存、调用构造函数、返回指针

有可能先返回指针当还没有调用构造函数导致对象没有初始化,其他线程获取到没有初始化的对象

版本四

C++

class Singleton4 {
public:
    static Singleton4* GetInstance() {
        Singleton4* tmp = instance.load(std::memory_order_relaxed);
        atomic_thread_fence(std::memory_order_acquire); // 获取内存屏障
        if (tmp == nullptr) {
            lock_guard lock(mutex_);
            tmp = instance.load(memory_order_relaxed);
            if (tmp == nullptr) {
                tmp = new Singleton4;
                atomic_thread_fence(std::memory_order_release); // 释放内存屏障
                instance.store(tmp,memory_order_relaxed);
                atexit(Destructor);
            }
        }
        return tmp;
    }
private:
    // 防止外界构造和删除对象
    Singleton4() = default;
    ~Singleton4() = default;
    Singleton4(const Singleton4&) = default;
    Singleton4& operator=(const Singleton4&) = default;

    static void Destructor() {
        if (instance != nullptr) {
            delete instance;
            instance = nullptr;
        }
    }

    static atomic instance;
    static mutex mutex_;
};

atomic Singleton4::instance;
mutex Singleton4::mutex_;

版本五

c++11 magic static 特性:如果当变量在初始化的时候,并发同时进⼊声明语句,并发线程将 会阻塞等待初始化结束

C++

class Singleton5 {
public:
    static Singleton5& GetInstance() {
        static Singleton5 instance;
        return instance;
    }
private:
    Singleton5() = default;
    ~Singleton5() = default;
    Singleton5(const Singleton5&) = default;
    Singleton5& operator=(const Singleton5&) = default;
};

版本六

C++

template
class Singleton6 {
public:
    static T& GetInstance() {
        static T instance;
        return instance;
    }
protected:
    virtual ~Singleton6() = default;
    Singleton6() = default;
    Singleton6(const Singleton6&) = default;
    Singleton6& operator=(const Singleton6&) = default;
};

class DesignPattern : public Singleton6 {
    friend class Singleton6;
public:
    ~DesignPattern() = default;

private:
    DesignPattern() = default;
    DesignPattern(const DesignPattern&) = default;
    DesignPattern& operator=(const DesignPattern&) = default;
};

int main() {
    DesignaPattern &d1 = new DesignaPattern::getInstance();
}

THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容