设计模式(003)创建型之单例模式

        单例模式是一种设计模式,用于确保一个类仅有一个实例,并提供全局访问点。该模式适用于需要全局唯一实例的场景,如数据库连接、日志记录器等。实现单例模式的方法有多种,下面分别介绍两种常用的实现方式。

一、饿汉式

饿汉式是指在类加载时就创建唯一实例,因此在调用该类的方法前就已经存在了一个实例。这种实现方式简单易懂,但在某些场景下可能会造成资源浪费,因为实例可能永远不会被用到。

1、场景设计

实现场景:用单例模式实现一个简单的加法计算

2、C++实现

静态变量 instance_ 在程序启动时就已经被创建,因此不需要使用互斥锁来保证线程安全。由于该实现没有懒加载,因此可能会浪费一些资源,但是可以确保线程安全。

#include <iostream>

using namespace std;

class Singleton {
    private:
        double operA;
        double operB;
        long result;
    private:
        Singleton() = default;
        ~Singleton() = default;
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
    public:
        static Singleton* getInstance();
        void setOperA(double value);
        void setOperB(double value);
        long getResult();

};

//成员函数定义
void Singleton::setOperA(double value){
    operA = value;
}

void Singleton::setOperB(double value){
    operB = value;
}

long Singleton::getResult(){
    result = operA + operB;
    return result;
}

Singleton* Singleton::getInstance(){
    static Singleton instance_;
    return &instance_;
}

int main()
{
    Singleton::getInstance()->setOperA(123);
    Singleton::getInstance()->setOperB(456);
    cout << Singleton::getInstance()->getResult() << endl;
    return 0;
}

3、Java实现

Singleton.java
package creatingpattern.singleton;

public class Singleton {
    /** 操作数A */
    int operA;
    /** 操作数B */
    int operB;
    /** 计算结果 */
    long result;

    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }

    public void setOperA(int operA) {
        this.operA = operA;
    }

    public void setOperB(int operB) {
        this.operB = operB;
    }

    public long getResult() {
        result = operA + operB;
        return result;
    }
}
SingletonDemo.java
package creatingpattern.singleton;

public class SingletonDemo {

    public static void main(String args[]) {
        Singleton.getInstance().setOperA(123);
        Singleton.getInstance().setOperB(456);
        System.out.println("result = " + Singleton.getInstance().getResult());
    }
}

二、懒汉式

懒汉式是指在第一次调用类的方法时才创建唯一实例,这种实现方式可以避免资源浪费,但需要在多线程环境下考虑线程安全问题。 

1、场景设计

实现场景:用单例模式实现一个简单的加法计算

2、C++实现

在懒汉式单例模式中,第一次调用 getInstance() 时才创建实例,如果有多个线程同时调用该函数,可能会同时创建多个实例,因此需要使用互斥锁来保证同步。在 instance_ 为空时,只有一个线程能够获取锁,其他线程需要等待直到锁被释放。注意,以下代码在Linux下使用g++进行编译可正常运行,在其他编译环境下有可能无法编译通过,比如QT环境下,因为MinGW尚未实现线程库。

#include <iostream>
#include <thread>
#include <mutex>
#include <unistd.h>

using namespace std;

class Singleton {
    private:
        static mutex mutex_;
        static Singleton* instance_;
        double operA;
        double operB;
        long result;
    public:
        static Singleton* getInstance() {
            if (instance_ == NULL) {
                lock_guard<mutex> lock(mutex_);
                if (instance_ == NULL) {
                    instance_ = new Singleton();
                }
            }
            return instance_;
        }
        void setOperA(double value);
        void setOperB(double value);
        long getResult();

    private:
        Singleton() = default;
        ~Singleton() = default;
        Singleton(const Singleton&) = delete;
        Singleton& operator=(const Singleton&) = delete;
};

mutex Singleton::mutex_;
Singleton* Singleton::instance_ = NULL;

//成员函数定义
void Singleton::setOperA(double value){
    operA = value;
}

void Singleton::setOperB(double value){
    operB = value;
}

long Singleton::getResult(){
    result = operA + operB;
    return result;
}

int main()
{
    Singleton::getInstance()->setOperA(123);
    Singleton::getInstance()->setOperB(456);
    cout << Singleton::getInstance()->getResult() << endl;
    return 0;
}

3、Java实现

注意:在多线程环境下,可能会出现多个线程同时进入 if (instance == null) 的情况,导致创建多个实例。为了避免这种情况,可以采用双重检查锁定或者静态内部类的方式实现懒汉式单例模式。

Singleton.java

package creatingpattern.singleton;

public class Singleton {
    private static volatile Singleton instance;
    /** 操作数A */
    int operA;
    /** 操作数B */
    int operB;
    /** 计算结果 */
    long result;

    private Singleton() {}

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

    public void setOperA(int operA) {
        this.operA = operA;
    }

    public void setOperB(int operB) {
        this.operB = operB;
    }

    public long getResult() {
        result = operA + operB;
        return result;
    }
}

SingletonDemo.java代码与饿汉式代码相同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值