设计模式 3 单例模式

设计模式 3

  • 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
  • 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

文章目录

  • [设计模式 3](#设计模式 3)
    • [单例模式(Singleton Pattern)](#单例模式(Singleton Pattern))
      • [1 定义](#1 定义)
      • [2 结构](#2 结构)
      • [3 示例代码](#3 示例代码)
        • [1. 懒汉式(Lazy Initialization)](#1. 懒汉式(Lazy Initialization))
        • [2. 线程安全的懒汉式](#2. 线程安全的懒汉式)
        • [3. 双重检查锁定(Double-Check Locking)](#3. 双重检查锁定(Double-Check Locking))
        • [4. 饿汉式(Eager Initialization)](#4. 饿汉式(Eager Initialization))
        • [5. 静态内部类(Static Inner Class)](#5. 静态内部类(Static Inner Class))
        • [6. 枚举(Enum)](#6. 枚举(Enum))
      • [4 特点](#4 特点)
      • [5 适用场景](#5 适用场景)

单例模式(Singleton Pattern)

1 定义

单例模式确保一个类只有一个实例,并提供一个访问该实例的全局访问点。它可以防止类被多次实例化,并且在某些情况下可以节省内存、确保一致性或控制资源的访问。

2 结构

单例模式的主要角色包括:

  • 单例类(Singleton): 包含一个私有的静态变量来保存单例实例,并提供一个公共的静态方法来返回这个实例。

UML 类图

scss 复制代码
+----------------------+
|      Singleton       |
+----------------------+
| - instance: Singleton|
+----------------------+
| + getInstance():     |
|   Singleton          |
+----------------------+

3 示例代码

单例模式的实现有多种方式,以下是最常见的几种。

1. 懒汉式(Lazy Initialization)

懒汉式实现中,实例在第一次调用 getInstance() 方法时才被创建。这种方式可以延迟实例的创建,节省资源,但在多线程环境下需要进行同步以保证线程安全。

csharp 复制代码
public class Singleton
{
    private static Singleton _instance;

    // 构造函数设置为私有,防止通过new创建实例
    private Singleton() { }

    public static Singleton GetInstance()
    {
        if (_instance == null)
        {
            _instance = new Singleton();
        }
        return _instance;
    }
}
2. 线程安全的懒汉式

为了保证线程安全,可以在 getInstance 方法上添加 lock 关键字,但这样可能会降低性能。

csharp 复制代码
public class Singleton
{
    private static Singleton _instance;
    private static readonly object _lock = new object();

    private Singleton() { }

    public static Singleton GetInstance()
    {
        lock (_lock)
        {
            if (_instance == null)
            {
                _instance = new Singleton();
            }
        }
        return _instance;
    }
}
3. 双重检查锁定(Double-Check Locking)

这种方法在检查实例是否已经存在时只加一次锁,提高了性能。这是线程安全且高效的实现方式。

csharp 复制代码
public class Singleton
{
    private static Singleton _instance;
    private static readonly object _lock = new object();

    private Singleton() { }

    public static Singleton GetInstance()
    {
        if (_instance == null)
        {
            lock (_lock)
            {
                if (_instance == null)
                {
                    _instance = new Singleton();
                }
            }
        }
        return _instance;
    }
}
4. 饿汉式(Eager Initialization)

饿汉式在类加载时就创建实例,因此不存在线程安全问题,但如果实例比较大且未使用时,会浪费资源。

csharp 复制代码
public class Singleton
{
    private static readonly Singleton _instance = new Singleton();

    // 构造函数设置为私有,防止通过new创建实例
    private Singleton() { }

    public static Singleton GetInstance()
    {
        return _instance;
    }
}
5. 静态内部类(Static Inner Class)

使用静态内部类的方式可以实现延迟加载和线程安全。静态内部类的实例只会在第一次被引用时初始化,因此可以实现懒加载效果。

csharp 复制代码
public class Singleton
{
    private Singleton() { }

    private static class SingletonHolder
    {
        internal static readonly Singleton _instance = new Singleton();
    }

    public static Singleton GetInstance()
    {
        return SingletonHolder._instance;
    }
}
6. 枚举(Enum)

使用枚举来实现单例是最简单和安全的方式,因为枚举实例化是线程安全的,并且只会被实例化一次。这种方式不仅实现了单例,而且还能防止反序列化和反射攻击。

csharp 复制代码
public enum Singleton
{
    Instance;

    public void SomeMethod()
    {
        Console.WriteLine("Singleton method called.");
    }
}

4 特点

  • 优点:

    • 控制实例数量: 确保系统中只有一个实例存在,减少内存开销。

    • 全局访问点: 提供了一个全局访问点,便于共享实例。

    • 避免资源冲突: 多个线程或进程访问同一资源时,单例模式可以有效地避免冲突。

  • 缺点:

    • 不易扩展: 由于单例类不能被继承,或者不应该被继承,导致其难以扩展。

    • 隐藏依赖: 单例模式通过全局访问点共享状态,可能导致隐藏依赖,使得代码难以理解和测试。

    • 多线程问题: 在多线程环境下实现单例模式需要小心处理,否则可能导致线程安全问题。

5 适用场景

  • 需要全局唯一实例的场景: 如线程池、数据库连接池、配置文件管理器等。
  • 需要控制资源的场景: 如打印机管理类,控制对同一资源的并发访问。
  • 需要共享状态的场景: 如应用程序的日志类,保证所有日志信息都记录到同一对象中。

单例模式在实际开发中非常常见,但在使用时要注意其潜在的缺陷,特别是在多线程和高并发的环境下,需要选择合适的实现方式以确保线程安全。

相关推荐
会敲代码的小张20 分钟前
设计模式-观察者模式
java·开发语言·后端·观察者模式·设计模式·代理模式
宗浩多捞24 分钟前
C++设计模式(更新中)
开发语言·c++·设计模式
秦哈哈29 分钟前
【软件设计】常用设计模式--观察者模式
观察者模式·设计模式
蔚一8 小时前
Java设计模式—面向对象设计原则(四) ----->接口隔离原则(ISP) (完整详解,附有代码+案例)
java·后端·设计模式·intellij-idea·接口隔离原则
严文文-Chris9 小时前
【设计模式-外观】
android·java·设计模式
yyqzjw11 小时前
【设计模式】观察者模式
算法·观察者模式·设计模式
Tech_gis11 小时前
C++ 常用设计模式
设计模式
java_heartLake12 小时前
设计模式之抽象工厂模式
设计模式·抽象工厂模式
codefly-xtl14 小时前
单例模式详解
java·单例模式·设计模式
爱编程的鱼16 小时前
JEE 设计模式
设计模式