单例模式,是一种创建型设计模式,他的核心思想是保证一个类只有一个实例(即,在整个应用程序中,只存在该类的一个实例对象,而不是创建多个相同类型的对象),并提供一个全局访问点来访问这个实例(即,其他类只能通过一个,可以是静态方法,来获取到这个唯一实例)。
优势:因为只有一个实例,既避免了多次创建相同的对象,节省了系统资源。多个类,也就是模块之间可以通过单例实例来共享数据;同时方便我们站在全局的角度控制唯一实例的访问(即,可以严格的控制客户怎样访问它、何时访问他);此外,单例模式还允许只在需要时才进行实例化,即所谓的懒加载,以提高程序的性能。
实现一个单例设计模式需要满足以下的基本要求:首先,任何外部代码不能够随意创建实例,也就意味着类的构造函数只能私有;其次,任何外部代码也不能够随意访问实例中的任何资源,也就意味着所有的静态实例变量须是私有的;最后,需要设置一个公有的静态方法,以便外部能够获取到实例的内部资源。
单例模式的实现方式有:懒汉式(只有在遇到请求实例时才会创建一个实例,并且如果已经创建过,就会返回已有的实例)、饿汉式(类加载时就已经完成了实例的创建,不管创建的实例在后面会不会使用,先创建再说)等。
在多线程环境下,由于饿汉式在程序启动阶段就完成实例的初始化,因此不存在多个线程同时尝试初始化实例的问题;但是懒汉式中多个线程同时访问 GetInstance() 方法,并且在同一时刻检测到实例没有被创建(只要线程切换足够频繁就有可能发生),就可能会同时创建实例,从而导致多个实例被创建,(好比你和小明都发现家里每米了,在你们没有相互通知的情况下,都会去超市买一袋米,这样就重复购买了,违背了单例模式)这种情况下我们可以采用一些同步机制,例如使用互斥锁来确保在任何时刻只有一个线程能够执行实例的创建。
以下是单例设计模式的基本写法,以Java代码为例:
- 饿汉式:
public class Singleton {
private static final Singleton instance = new Singleton(); // 类加载时就被创建
private Singleton() {
// 私有构造方法,防止外部实例化
}
public static Singleton getInstance() {
return instance;
}
}
- 懒汉式 + 互斥锁:
public class Singleton {
private static final Singleton instance;
private Singleton() {
// 私有构造方法,防止外部实例化
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance == new Singleton();
}
return instance;
}
}
- 懒汉式 + 双重检查锁提高性能:
public class Singleton {
private static final Singleton instance;
private Singleton() {
// 私有构造方法,防止外部实例化
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance == new Singleton();
}
}
}
return instance;
}
}
总结一下,我们应当什么时候使用单例设计模式:
- 如果多个模块都需要共享某一种资源,例如一个全局的配置管理器来存储管理配置信息、管理数据库连接池信息等,可以使用单例设计模式。
- 如果创建对象本身就比较消耗资源,而且可能在整个程序中都不一定会使用,就可以使用单例模式中的懒加载;
- 有些场景中只需要一个实例就足以协调所有行为,创建多个实例没有必要甚至会导致不好的后果,例如管理应用程序中的缓存、管理线程池。
【设计模式专题之单例模式】1.小明的购物车
CPP版本:
#include <iostream>
#include <vector>
#include <map>
using namespace std;
class ShoppingCartManager {
public:
// 获取购物车实例
static ShoppingCartManager& getInstance() {
static ShoppingCartManager instance;
return instance;
}
// 添加商品到购物车
void addToCart(const string& itemName, int quantity) {
if (cart.find(itemName) == cart.end()) {
order.push_back(itemName);
}
cart[itemName] += quantity;
}
// 查看购物车
void viewCart() const {
for (const auto& itemName : order) {
cout << itemName << " " << cart.at(itemName) << endl;
// 不能使用cart[itemName],因为处在一个const方法,不能有修改变量值的格式出现。
}
}
private:
// 私有构造函数
ShoppingCartManager() {}
// 购物车存储商品和数量的映射
map<string, int> cart;
// 记录加入购物车的顺序
vector<string> order;
};
int main() {
string itemName;
int quantity;
while (cin >> itemName >> quantity) {
// 获取购物车实例并添加商品
ShoppingCartManager& cart = ShoppingCartManager::getInstance();
cart.addToCart(itemName, quantity);
}
// 输出购物车内容
const ShoppingCartManager& cart = ShoppingCartManager::getInstance();
cart.viewCart();
return 0;
}