第2课设计模式_单例模式
热度🔥:44 免费课程
授课语音
单例模式(Singleton Pattern)
1. 介绍
单例模式是一种设计模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点来访问该实例。
单例模式的核心概念
- 唯一性:确保一个类只有一个实例。即使多个线程尝试创建该类的对象,也只会存在一个实例。
- 全局访问:单例模式提供一个全局访问点来获取这个唯一实例,通常通过静态方法实现,以便在任何地方都可以访问该实例。
- 延迟初始化:在一些实现中,单例实例在第一次被请求时才被创建,这样可以避免不必要的开销。这一过程称为延迟初始化(lazy initialization)。
单例模式的变体
- 懒汉式单例(Lazy Initialization):在第一次被访问时创建实例,优点是延迟初始化,但需要处理多线程环境下的同步问题。
- 饿汉式单例(Eager Initialization):在类加载时就创建实例,这种方式简单且线程安全,但如果实例创建的开销较大而应用从未使用该实例,则可能会造成资源浪费。
- 双重检查锁(Double-Check Locking):在多线程环境下,通过双重检查和锁机制来确保实例创建的线程安全性。通常结合
volatile
关键字使用以避免指令重排序带来的问题。 - 登记式单例(Registry-based Singleton):使用注册表管理单例实例。通过静态方法或其他机制从注册表中获取单例实例,适合需要支持动态实例管理的场景。
- 枚举单例(Enum Singleton):使用枚举类型实现单例模式,这是 Java 推荐的实现方式,能够确保线程安全,并防止反序列化攻击。
实际框架中的应用
单例模式在许多实际框架和系统中有广泛的应用。以下是一些常见的应用场景:
配置管理:在TypeScript框架中,配置管理类通常使用单例模式。例如,一些TypeScript库的配置类可能实现为单例,以确保在整个应用程序中配置的一致性。
数据库连接池:数据库连接池通常使用单例模式来管理连接。例如,在TypeScript应用中,使用连接池的库(如TypeORM或Sequelize)通常会实现为单例,以确保高效管理数据库连接。
日志记录:TypeScript中的日志记录器通常使用单例模式来确保日志记录的一致性。例如,一些TypeScript日志库(如Winston或Pino)可以配置为单例,以便在整个应用程序中共享同一个日志记录器实例。
缓存系统:缓存系统通常使用单例模式,确保在整个应用程序中只有一个缓存实例,从而提高性能和资源利用率。TypeScript可以利用Map或其他数据结构实现这样的缓存。
TypeScript应用:在TypeScript应用中,某些全局配置或服务可能被设计为单例,以确保在整个应用程序上下文中只存在一个实例,从而保证共享服务和配置的一致性。
这些场景展示了单例模式在TypeScript平台上的广泛应用,能够有效管理资源和提供一致性。
2. 代码案例
以下是将您的单例模式示例转换为TypeScript的版本:
class SingletonExamples {
// 1. 饿汉式单例(Eager Initialization)
class EagerSingleton {
private static instance: EagerSingleton = new EagerSingleton();
private value: string;
private constructor() {
this.value = "EagerSingleton Value";
}
public static getInstance(): EagerSingleton {
return this.instance;
}
public showValue(): void {
console.log(`EagerSingleton value: ${this.value}`);
}
}
// 2. 懒汉式单例(Lazy Initialization)
class LazySingleton {
private static instance: LazySingleton | null = null;
private static lock: any = {}; // 锁对象
private value: string;
private constructor() {
this.value = "LazySingleton Value";
}
public static getInstance(): LazySingleton {
if (this.instance === null) {
// 第一次检查
synchronized(this.lock, () => {
if (this.instance === null) { // 第二次检查
this.instance = new LazySingleton();
}
});
}
return this.instance;
}
public showValue(): void {
console.log(`LazySingleton value: ${this.value}`);
}
}
// 3. 双重检查锁(Double-Check Locking)
class DoubleCheckLockingSingleton {
private static instance: DoubleCheckLockingSingleton | null = null;
private static lock: any = {}; // 锁对象
private value: string;
private constructor() {
this.value = "DoubleCheckLockingSingleton Value";
}
public static getInstance(): DoubleCheckLockingSingleton {
if (this.instance === null) {
// 第一次检查
synchronized(this.lock, () => {
if (this.instance === null) { // 第二次检查
this.instance = new DoubleCheckLockingSingleton();
}
});
}
return this.instance;
}
public showValue(): void {
console.log(`DoubleCheckLockingSingleton value: ${this.value}`);
}
}
// 4. 登记式单例(Registry-based Singleton)
class RegistrySingleton {
private static registry: { [key: string]: RegistrySingleton } = {}; // 注册表
private value: string;
private constructor() {
this.value = "RegistrySingleton Value";
}
public static getInstance(key: string): RegistrySingleton {
if (!(key in this.registry)) {
this.registry[key] = new RegistrySingleton(); // 动态管理单例
}
return this.registry[key];
}
public showValue(): void {
console.log(`RegistrySingleton value: ${this.value}`);
}
}
// 5. 枚举单例(Enum Singleton)
enum EnumSingleton {
INSTANCE // 定义唯一的枚举实例
}
public static showEnumValue(): void {
console.log("EnumSingleton value: EnumSingleton Value");
}
}
// 示例代码
const main = () => {
// 1. 饿汉式单例
const eager1 = SingletonExamples.EagerSingleton.getInstance();
eager1.showValue();
// 2. 懒汉式单例
const lazy1 = SingletonExamples.LazySingleton.getInstance();
lazy1.showValue();
// 3. 双重检查锁
const doubleCheck1 = SingletonExamples.DoubleCheckLockingSingleton.getInstance();
doubleCheck1.showValue();
// 4. 登记式单例
const registry1 = SingletonExamples.RegistrySingleton.getInstance("key1");
registry1.showValue();
// 5. 枚举单例
SingletonExamples.showEnumValue();
};
main();
详细中文注释
- 类说明:每个单例实现类都有一个私有构造函数,用于设置初始值。在每个
showValue
方法中打印该实例的值,以验证实例的唯一性。 - 示例代码:在主程序中,我们创建每种单例的实例并调用相应的方法以验证单例模式的有效性。