继承实现单例模式的探索(二)
前言
本篇文章继续探索通过继承实现单例模式的可行方案,这次的方案将采用反射机制隐式创建派生类实例,示例代码为C#。
代码
v1.0
using System.Reflection;/// <summary>
/// 单例模式基类
/// </summary>
/// <typeparam name="T">单例类型</typeparam>
public abstract class Singleton<T>
where T : class
{public static T instance => _instance.Value;static readonly Lazy<T> _instance = new Lazy<T>(Create);#pragma warning disable CS8603static T Create(){return Activator.CreateInstance(typeof(T),BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,null, null, null) as T;}
#pragma warning restore CS8603
}
测试
单例模式基类
/// <summary>
/// 单例模式基类
/// </summary>
/// <typeparam name="T">单例类型</typeparam>
public abstract class SingletonWithTest<T>
where T : class
{public static T instance => _instance.Value;static readonly Lazy<T> _instance = new Lazy<T>(Create);#pragma warning disable CS8603static T Create(){return Activator.CreateInstance(typeof(T),BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,null, null, null) as T;}
#pragma warning restore CS8603
}
派生类
public class TestA : SingletonWithTest<TestA>
{public readonly string key;TestA() { key = "Default A"; }
}public class TestB : SingletonWithTest<TestB>
{public readonly string key;public TestB() { key = "Default B"; }
}public class TestC : SingletonWithTest<TestC>
{public readonly string key;public TestC(string key) { this.key = key; }
}public class TestD : SingletonWithTest<TestD>
{public readonly string key;public TestD() { key = "Default D"; }public TestD(string key) { this.key = key; }
}public class TestE : SingletonWithTest<TestE>
{public readonly string key;TestE() { key = "Default E"; }public TestE(string key) { this.key = key; }
}public class TestF : SingletonWithTest<TestF>
{public readonly string key = "Default F";
}
测试代码
// ********************************* 线程安全测试:通过 *********************************Thread t1, t2, t3, t4, t5, t6;// 打印同一单例的 HashCode 测试:通过
// t1 = new Thread(() => Console.WriteLine("Thread1:" + TestA.instance.GetHashCode()));
// t2 = new Thread(() => Console.WriteLine("Thread2:" + TestA.instance.GetHashCode()));
// t3 = new Thread(() => Console.WriteLine("Thread3:" + TestA.instance.GetHashCode()));
// t4 = new Thread(() => Console.WriteLine("Thread4:" + TestA.instance.GetHashCode()));
// t5 = new Thread(() => Console.WriteLine("Thread5:" + TestA.instance.GetHashCode()));
// t6 = new Thread(() => Console.WriteLine("Thread6:" + TestA.instance.GetHashCode()));// 同时使用不同单例的测试:通过
t1 = new Thread(() => Console.WriteLine("Thread1:" + TestA.instance.GetHashCode()));
t2 = new Thread(() => Console.WriteLine("Thread2:" + TestB.instance.GetHashCode()));
t3 = new Thread(() => Console.WriteLine("Thread3:" + TestC.instance.GetHashCode())); // 没有无参构造函数,触发异常
t4 = new Thread(() => Console.WriteLine("Thread4:" + TestD.instance.GetHashCode()));
t5 = new Thread(() => Console.WriteLine("Thread5:" + TestE.instance.GetHashCode()));
t6 = new Thread(() => Console.WriteLine("Thread6:" + TestF.instance.GetHashCode()));t1.Start();
t2.Start();
t3.Start();
t4.Start();
t5.Start();
t6.Start();t1.Join();
t2.Join();
t3.Join();
t4.Join();
t5.Join();
t6.Join();
优缺点分析
| 优点 | 1.继承实现单例模式; 2.按需加载,延迟初始化; 3.线程安全; 4.可以通过单例基类规范统一标准; 5.派生类的无参构造函数用于初始化; 6.将派生类实例创建权限交由派生类本身决定,通常,为遵循单例模式的原则应向外部关闭通过new关键字显式调用构造函数的权限,但这对派生类而言并非硬性要求; |
|---|---|
| 缺点 | 1.反射开销; 2.派生类必须具备无参构造函数,且无参构造函数需要向单例基类提供可进行反射访问的权限; |
版本改进
......
系列文章
继承实现单例模式的探索(一)
如果这篇文章对你有帮助,请给作者点个赞吧!
相关文章:
继承实现单例模式的探索(二)
前言 本篇文章继续探索通过继承实现单例模式的可行方案,这次的方案将采用反射机制隐式创建派生类实例,示例代码为C#。 代码 v1.0 using System.Reflection;/// <summary> /// 单例模式基类 /// </summary> /// <typeparam name"T&…...
设计模式-访问者模式
访问者模式(Visitor):表示一个作用于某对象结构中的各元素的操作,使得在不改变个元素的类的前提下定义作用于这些元素的新操作。...
国创——基于Unity3D和MediaPipe构建虚拟人物驱动系统
以下是一个基于Unity3D和MediaPipe构建虚拟人物驱动系统的基本概念和简化的Python示例代码框架。请注意,这只是一个基础示例,实际应用中可能需要更多的完善和调整。 一、整体概念 1. MediaPipe - MediaPipe是一个用于构建多模态(例如视频、…...
环境可靠性
一、基础知识 1.1 可靠性定义 可靠性是指产品在规定的条件下、在规定的时间内完成规定的功能的能力。 可靠性的三大要素:耐久性、可维修性、设计可靠性 耐久性:指的是产品能够持续使用而不会故障的特性,或者说是产品的使用寿命。 可维修性&a…...
Chromium 设置页面打开系统代理源码分析c++
1、前端页面调用showProxySettings() {chrome.send("showProxySettings")} 2、c 响应代码如下 chrome\browser\ui\webui\settings\system_handler.ccvoid SystemHandler::RegisterMessages() {web_ui()->RegisterMessageCallback("showProxySettings",b…...
信号检测理论(Signal Detection Theory, SDT)
信号检测理论(Signal Detection Theory, SDT)模拟是一种实验设计,用于研究和理解在存在噪声或不确定性的情况下如何做出决策。在心理学、认知科学、工程学和许多其他领域,信号检测理论都非常重要。 一、基础概念: 在信…...
Flink源码剖析
写在前面 最近一段时间都没有更新博客了,原因有点离谱,在实现flink的两阶段提交的时候,每次执行自定义的notifyCheckpointComplete时候,好像就会停止消费数据,完成notifyComplete后再消费数据;基于上述原因…...
[Python学习日记-39] 闭包是个什么东西?
[Python学习日记-39] 闭包是个什么东西? 简介 闭包现象 闭包意义与作用 简介 在前面讲函数和作用域的时候应该提到过,当函数运行结束后会由 Python 解释器自带的垃圾回收机制回收函数内作用域已经废弃掉的变量,但是在 Python 当中还有一种…...
XSLT 实例:掌握 XML 转换的艺术
XSLT 实例:掌握 XML 转换的艺术 引言 XSLT(可扩展样式表语言转换)是一种强大的工具,用于将 XML(可扩展标记语言)文档转换为其他格式,如 HTML、PDF 或纯文本。在本文中,我们将通过一…...
【C++】第一节:C++入门
1、C关键字 2、命名空间 在C/C中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染&am…...
CSP-S 2021 T1廊桥分配
CSP-S 2021 T1廊桥分配 枚举分配给国内航班和国外航班的廊桥数量,若分配给国内机场 i i i个廊桥,则国外机场就有 n − i n-i n−i个廊桥,在此基础上分别判断两边各能通过多少飞机。用一个小根堆存储飞机离开的时间,枚举到一个飞机…...
项目配置说明
文章目录 一、下载 vscode 并安装相应扩展1.1 下载 vscode1.2 安装扩展 二、git 项目三、git 提交流程3.1 确定要提交的代码 四、git 拉新流程 一、下载 vscode 并安装相应扩展 1.1 下载 vscode vscode 我已经发群里了,或者自己去官网下载也行 1.2 安装扩展 打开…...
linux网络编程实战
前言 之前找工作的之后写了一些网络编程的笔记和代码,然后现在放到csdn上保存一下。有几个版本的,看看就好。就是简单的实现一下服务端和客户端之间的交互的,还没有我之前上linux编程课写的代码复杂。 哦对了,这个网络编程的代码对…...
网络基础 【HTTP】
💓博主CSDN主页:麻辣韭菜💓 ⏩专栏分类:Linux初窥门径⏪ 🚚代码仓库:Linux代码练习🚚 💻操作环境: CentOS 7.6 华为云远程服务器 🌹关注我🫵带你学习更多Linux知识…...
[Linux#61][UDP] port | netstat | udp缓冲区 | stm32
目录 0. 预备知识 1. 端口号的划分范围 2. 认识知名端口号 3. netstat 命令 4. pidof 命令 二.UDP 0.协议的学习思路 1. UDP 协议报文格式 报头与端口映射: 2. UDP 的特点 面向数据报: 3. UDP 的缓冲区 4. UDP 使用注意事项 5. 基于 UDP 的…...
定义类方法的错误总结
struct Renderer {vector<function<void(vector<string>)>> fileDropListeners;// 定义一个方法,它是将一个函数作为输入,callback是形参void print(function<void(float)> callback_func);void onFileDrop(function<void(ve…...
Redis --- 第三讲 --- 通用命令
一、get和set命令 Redis中最核心的两个命令 get 根据key来取value set 把key和value存储进去 redis是按照键值对的方式存储数据的。必须要先进入到redis客户端。 语法 set key value : key和value都是字符串。 对于上述这里的key value 不需要加上引号&#…...
【Linux】进程间关系与守护进程
超出能力之外的事, 如果永远不去做, 那你就永远无法进步。 --- 乌龟大师 《功夫熊猫》--- 进程间关系与守护进程 1 进程组2 会话3 控制终端4 作业控制5 守护进程 1 进程组 之前我们提到了进程的概念, 其实每一个进程除了有一个进程 ID(P…...
【可视化大屏】将柱状图引入到html页面中
到这里还是用的死数据,先将柱状图引入html页面测试一下 根据上一步echarts的使用步骤,引入echarts.js后需要初始化一个实例对象,所以新建一个index.js文件来进行创建实例化对象和配置数据信息等。 //在index.html引入<script src"j…...
gm/ID设计方法学习笔记(一)
前言:为什么需要gm/id (一)主流设计方法往往侧重于强反型区(过驱>0.2V),低功耗设计则侧重于弱反型区(<0),但现在缺乏对中反型区的简单和准确的手算模型。 1.对于…...
智能材料科技:COMSOL金属的SPP技术及其降维降损解决方案的研究与实践
comsol金属spp降维降损。金属表面等离子体激元(SPP)的模拟总让人又爱又恨——高局域场增强的特性是真香,但三维全波仿真动不动就内存爆炸也是真头疼。最近在COMSOL里折腾SPP降维模型时发现,只要玩点几何骚操作,计算量能…...
AI_NovelGenerator:如何在7天内完成传统写作需要3个月的长篇小说创作
AI_NovelGenerator:如何在7天内完成传统写作需要3个月的长篇小说创作 【免费下载链接】AI_NovelGenerator 使用ai生成多章节的长篇小说,自动衔接上下文、伏笔 项目地址: https://gitcode.com/GitHub_Trending/ai/AI_NovelGenerator 问题诊断&…...
NumPy 应用实例:用户行为数据分析(归一化和标准化处理)
在用户行为分析中,常常需要同时处理多个特征,例如访问次数、消费金额、停留时长、收藏数量等。这些特征虽然都能反映用户活跃程度或消费倾向,但它们的单位、量纲和取值范围通常并不一致。如果直接将原始数据用于综合评分或相似度计算…...
Xilinx FPGA FIFO IP核复位机制深度解析与实战调试
1. Xilinx FPGA FIFO IP核复位机制基础解析 第一次接触Xilinx FPGA的FIFO IP核时,很多人都会在复位环节栽跟头。我刚开始用Vivado生成FIFO IP核时,就遇到过复位信号处理不当导致数据丢失的问题。FIFO(First In First Out)作为数据…...
3步实现Axure RP本地化界面优化:开源工具助力中文设计环境构建
3步实现Axure RP本地化界面优化:开源工具助力中文设计环境构建 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包,不定期更新。支持 Axure 9、Axure 10。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-c…...
开源入门踩坑全实录:从PR被拒到核心贡献者的全周期避坑指南
根据中国开源软件推进联盟2025年发布的《中国开源开发者生态报告》,国内开源开发者规模已突破1200万,但入门1年内就停止贡献的开发者占比高达78.6%。换句话说,每5个尝试入门开源的新手,就有4个会在一年内彻底放弃。 作为从0起步&a…...
GIL消失后的混沌现场:共享对象修改异常、原子性丢失、引用计数溢出,一文收全7种致命报错及防御代码模板
第一章:GIL消失后的并发危机全景图当CPython的全局解释器锁(GIL)真正消失,Python将首次具备原生、安全的多线程并行执行能力。但这并非一劳永逸的性能飞跃,而是一场系统级并发范式的重构风暴——内存模型、对象生命周期…...
手把手教你用ZPL指令在Zebra打印机上打印动态条码(附完整代码示例)
手把手教你用ZPL指令在Zebra打印机上打印动态条码(附完整代码示例) 在物流仓储、零售结算和智能制造场景中,自动生成并打印条码标签是提升作业效率的关键环节。Zebra打印机凭借其工业级稳定性和ZPL语言的高效指令集,成为行业标配…...
Paimon数据湖实战:Merge Engines深度解析与应用场景
1. Paimon数据湖中的Merge Engines核心机制 第一次接触Paimon的Merge Engines时,我完全被它强大的数据合并能力震撼到了。这就像是一个智能的数据管家,能够根据不同的业务需求,自动帮你处理各种复杂的数据合并场景。在实际项目中,…...
Anlogic FD工具深度体验:如何用eMCU软核实现SF1芯片的PSRAM控制器设计
Anlogic FD工具实战:基于eMCU软核的PSRAM控制器设计进阶指南 当FPGA工程师需要在资源受限的SF1芯片上实现高性能存储控制时,Anlogic Future Dynasty(FD)工具链中的eMCU软核与PSRAM控制器组合提供了绝佳的解决方案。不同于基础教程…...
