23种设计模式之《单例模式(Singleton)》在c#中的应用及理解

ops/2025/2/22 0:18:02/

程序设计中的主要设计模式通常分为三大类,共23种:

1. 创建型模式(Creational Patterns)

  • 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点。

  • 工厂方法模式(Factory Method):定义创建对象的接口,由子类决定实例化哪个类。

  • 抽象工厂模式(Abstract Factory):提供一个创建一系列相关或依赖对象的接口,而无需指定具体类。

  • 建造者模式(Builder):将一个复杂对象的构建与其表示分离,使同样的构建过程可以创建不同的表示。

  • 原型模式(Prototype):通过复制现有对象来创建新对象。

2. 结构型模式(Structural Patterns)

  • 适配器模式(Adapter):将一个类的接口转换成客户希望的另一个接口。

  • 桥接模式(Bridge):将抽象部分与实现部分分离,使它们可以独立变化。

  • 组合模式(Composite):将对象组合成树形结构以表示“部分-整体”的层次结构。

  • 装饰器模式(Decorator):动态地给对象添加职责,相比生成子类更为灵活。

  • 外观模式(Facade):为子系统中的一组接口提供一个统一的接口。

  • 享元模式(Flyweight):通过共享技术有效地支持大量细粒度对象。

  • 代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问。

3. 行为型模式(Behavioral Patterns)

  • 责任链模式(Chain of Responsibility):使多个对象都有机会处理请求,从而避免请求的发送者与接收者耦合。

  • 命令模式(Command):将请求封装为对象,使你可以用不同的请求对客户进行参数化。

  • 解释器模式(Interpreter):给定一个语言,定义其文法的一种表示,并定义一个解释器。

  • 迭代器模式(Iterator):提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露其内部表示。

  • 中介者模式(Mediator):定义一个中介对象来封装一系列对象之间的交互。

  • 备忘录模式(Memento):在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。

  • 观察者模式(Observer):定义对象间的一对多依赖关系,当一个对象改变状态时,所有依赖者都会收到通知并自动更新。

  • 状态模式(State):允许对象在其内部状态改变时改变其行为。

  • 策略模式(Strategy):定义一系列算法,将它们封装起来,并使它们可以互相替换。

  • 模板方法模式(Template Method):定义一个操作中的算法骨架,将一些步骤延迟到子类中。

  • 访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作,使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

下面是一个使用C#实现的单例模式示例代码,并附有详细的文字说明。

4. 单例模式代码示例

csharp

using System;public class Singleton
{// 1. 定义一个静态变量来保存类的唯一实例private static Singleton _instance;// 2. 私有构造函数,防止外部通过new创建实例private Singleton(){Console.WriteLine("Singleton instance created.");}// 3. 提供一个全局访问点来获取唯一实例public static Singleton GetInstance(){// 如果实例不存在,则创建一个新的实例if (_instance == null){_instance = new Singleton();}return _instance;}// 4. 示例方法public void DoSomething(){Console.WriteLine("Doing something in Singleton instance.");}
}class Program
{static void Main(string[] args){// 获取单例实例Singleton singleton1 = Singleton.GetInstance();Singleton singleton2 = Singleton.GetInstance();// 调用实例方法singleton1.DoSomething();singleton2.DoSomething();// 检查两个实例是否相同if (singleton1 == singleton2){Console.WriteLine("singleton1 and singleton2 are the same instance.");}else{Console.WriteLine("singleton1 and singleton2 are different instances.");}}
}

5. 代码说明

  1. 静态变量 _instance

    • _instance 是一个静态变量,用于保存类的唯一实例。

    • 由于是静态的,它在整个应用程序生命周期中只会存在一个实例。

  2. 私有构造函数

    • 构造函数被声明为 private,防止外部代码通过 new 关键字直接创建实例。

    • 这是单例模式的核心,确保类的实例化只能由类自身控制。

  3. 全局访问点 GetInstance

    • GetInstance 是一个静态方法,用于提供对单例实例的全局访问。

    • 如果 _instance 为 null,则创建一个新的实例并赋值给 _instance;否则直接返回现有的实例。

    • 这种方法称为“懒汉式单例”,因为实例是在第一次访问时才创建的。

  4. 示例方法 DoSomething

    • 这是一个普通的方法,用于演示单例实例的功能。

    • 你可以通过单例实例调用这个方法。

  5. 主程序验证

    • 在 Main 方法中,通过 GetInstance 获取两个单例实例 singleton1 和 singleton2

    • 调用它们的 DoSomething 方法,并检查它们是否是同一个实例。

    • 如果输出显示 singleton1 和 singleton2 是同一个实例,则说明单例模式实现成功。


6. 输出结果

运行上述代码后,输出如下:

Singleton instance created.
Doing something in Singleton instance.
Doing something in Singleton instance.
singleton1 and singleton2 are the same instance.

7. 单例模式的特点

  1. 唯一性

    • 确保一个类只有一个实例。

  2. 全局访问点

    • 提供一个全局访问点,方便其他代码获取该实例。

  3. 延迟初始化

    • 实例在第一次被访问时才创建,节省资源。

  4. 线程安全问题

    • 上述代码在单线程环境下是安全的,但在多线程环境下可能会创建多个实例。

    • 可以通过加锁(lock)或使用静态构造函数来确保线程安全。


8. 线程安全的单例模式(改进版)

如果需要支持多线程环境,可以使用以下改进版代码:

csharp

using System;public class Singleton
{private static readonly object _lock = new object();private static Singleton _instance;private Singleton(){Console.WriteLine("Singleton instance created.");}public static Singleton GetInstance(){if (_instance == null){lock (_lock){if (_instance == null){_instance = new Singleton();}}}return _instance;}public void DoSomething(){Console.WriteLine("Doing something in Singleton instance.");}
}
  • 使用 lock 关键字确保多线程环境下只有一个线程可以创建实例。

  • 双重检查锁定(Double-Check Locking)进一步优化性能,避免每次访问都加锁。


http://www.ppmy.cn/ops/160052.html

相关文章

golang--字符串处理(runeleixing )

在 Go 语言中,rune 类型是一个非常重要的基础类型,用于处理 Unicode 字符。以下是关于 rune 类型的详细用法说明: 一、基础概念 类型定义 rune 是 int32 的别名(type rune int32),表示一个 Unicode 码点&a…

【计算机网络】TCP三次握手

三次握手(Three-Way Handshake)是 TCP(传输控制协议) 建立连接的过程,确保通信双方能够同步序列号并确认彼此的收发能力。这个过程是 TCP 可靠性的基础,以下是三次握手的详细步骤: 如下图所示&a…

了解rtc_time64_to_tm()和rtc_tm_to_time64()

rtc_time64_to_tm()和rtc_tm_to_time64()主要用于RTC的驱动程序,在Linux外部RTC驱动中较常见。 打开“drivers/rtc/lib.c” /* * rtc_time64_to_tm - Converts time64_t to rtc_time. * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. */ //将ti…

【从0做项目】Java搜索引擎(8) 停用词表 正则

阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 文章导读 零:项目结果展示 一:前引 二:停用词表 1:…

【Docker】未来已来 | Docker技术在云计算、边缘计算领域的应用前景

欢迎来到英杰社区: https://bbs.csdn.net/topics/617804998 欢迎来到阿Q社区: https://bbs.csdn.net/topics/617897397 📕作者简介:热爱跑步的恒川,致力于C/C、Java、Python等多编程语言,热爱跑步&#xff…

读《算法笔记》有感——杂记

读《算法笔记》有感 为了考研复试,我尝试过《代码随想录》《Cprime》《数据结构–严蔚敏》《程序设计–谭浩强》《C》(某个不知名二本出的教材)还有《算法笔记》。在阅读《算法笔记》后,我直接climax,它很好的把我大学4年疑惑的知识点给讲明…

Jedis 客户端 用于java连接redis服务

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId

公证 网络安全

您是否需要非常高吞吐量的Corda网络&#xff1f; 网络的吞吐量是否稳定&#xff1f; 您是否已经从其他领域挤出了所有可能的表现&#xff1f; 如果您对这些问题的回答是“是”&#xff0c;那么我可能会为您提供一些有用的信息。 我列出了这些问题&#xff0c;以减少您过早优化C…