【设计模式】之单例模式(Singleton)

单例模式的定义为:保证一个类只有一个实例,并且提供一个全局的访问入口。

Ensure a class only has one instance, and provide a global point of access it.


虽然说,单例模式在所有的模式当中算是比较简单的一个,但是如果牵扯到线程安全问题,似乎没有那么简单。

本文参考《Head First》和《Design Patterns》举例说明单例模式的使用方法和注意事项。


为什么我们不用全局变量,而使用单例呢?

原因大致有四点,第一,全局变量不是OO设计所提倡的;第二,使用全局变量的形式并不能阻止用户创建多个类的实例;第三,对全局变量不能高效地使用lazy initialization。

当然如果静态类是self-constraint,当然可以使用,但是好多时候,对象是需要依赖外部状态的,并且静态类是不能够被继承的。


《Head First》中不提倡subclass单例,因为Singletons are meant to be used sparingly.

《Design Patterns》中,subclass单例后,可以不改变使用着的代码作为单例模式的一个优势来介绍,而且单例模式可以不“单例”,可以创建多个实例。

以下C++代码,则实现了如此功能,当然生成多个实例的单例模式有很多弊端,在本例中,子类的必须实例化才能够在registry中注册,因此违背了lazy initialization的原则。

// singleton.h
#ifndef _HEADER_SINGLETON_
#define _HEADER_SINGLETON_
#include <map>
#include <cstddef>
#include <iostream>
#include <string>
using namespace std;

class Singleton {
public:
    static void Register(const string& name, Singleton*);
    static Singleton* Instance();

    virtual void tell() {
        cout << "I am class Singleton" << endl;
    }
protected:
    static Singleton* Lookup(const string& name);

private:
    static map<string, Singleton*> _registry;
    static Singleton* _instance;
};
#endif // _HEADER_SINGLETON_

// singleton.cpp
#include "singleton.h"
#include <cstddef>
#include <cstdio>
#include <cstdlib>
using namespace std;

Singleton* Singleton::_instance = NULL;
map<string, Singleton*> Singleton::_registry = map<string, Singleton*>();

void Singleton::Register(const string& name, Singleton* singleton) {
    _registry[name] = singleton;
}

Singleton* Singleton::Instance() {
    if (_instance == 0) {
        const char* singletonName = getenv("SINGLETON");
        // user or environment supplies this at startup

        _instance = Lookup(singletonName);
        // Lookup returns 0 if there's no such singleton
    }
    return _instance;
}

Singleton* Singleton::Lookup(const string& name) {
    if (_registry.count(name)) {
        return _registry[name];
    }
    return NULL;
}

#ifndef _HEADER_MY_SINGLETON_
#define _HEADER_MY_SINGLETON_

#include "singleton.h"

class MySingleton : public Singleton {
public:
    virtual void tell() {
        cout << "I am class MySingleton" << endl;
    }

protected:
    MySingleton() {
        Singleton::Register("mysingleton", this);
    }

private:
    static MySingleton _my_singleton;
};

#endif // _HEADER_MY_SINGLETON_

#include "mysingleton.h"

MySingleton MySingleton::_my_singleton = MySingleton();
本例中忽略了线程安全等问题。


在java中倒是可以很简单的写出线程安全的单例模式。

public class ChocolateBoiler {
    private boolean empty;
    private boolean boiled;
    private volatile static ChocolateBoiler uniqueInstance;
     
    private ChocolateBoiler() {
        empty = true;
        boiled = false;
    }

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

    public void fill() {
        if (isEmpty()) {
            empty = false;
            boiled = false;
        }
    }

    public void drain() {
        if (!isEmpty() && isBoiled()) {
            empty = true;
        }
    }

    public void boil() {
        if (!isEmpty() && !isBoiled()) {
            boiled = true;
        }
    }

    public boolean isEmpty() {
        return empty;
    }

    public boolean isBoiled() {
        return boiled;
    }
}
关于此处几个关键字,具体可以参见《Header First Design Patterns》介绍singleton章节。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值