3.单例模式问题1:构造函数

一、C# 构造函数与单例模式安全性

1. 单例模式存在的问题

复制代码
public class Singleton<T> where T : class, new()
{
    private static T instance;
    public static T Instance
    {
        get
        {
            instance ??= new T();
            return instance;
        }
    }
}

通过new T()创建实例。但是这种方式存在一个问题:外部代码可以直接 new 单例对象,破坏单例唯一性

二、限制外部创建对象

1. 私有构造函数

解决方式:将构造函数设置为private

这样外部无法:new GameManager();

只能:GameManager.Instance来获取对象。

三、私有构造函数带来的问题

如果单例基类中:instance = new T();

要求:where T : new()

但是:私有构造函数不能满足 new() 约束,二者冲突了。

四、通过反射创建私有构造函数对象

解决方式:取消new()约束,改为where T : class,然后通过反射调用私有构造函数。

复制代码
using System;
using System.Reflection;

public abstract class Singleton<T> where T : class
{
    private static T instance;
    public static T Instance
    {
        get
        {
            if(instance == null)
            {
                Type type = typeof(T);
                ConstructorInfo constructor =type.GetConstructor(
                        BindingFlags.Instance | BindingFlags.NonPublic,
                        null,
                        Type.EmptyTypes,
                        null
                    );
                if(constructor != null)
                {
                    instance = constructor.Invoke(null) as T;
                }
            }
            return instance;
        }
    }
}

五、反射获取构造函数

Type

获取类型信息:typeof(T)

GetConstructor()

获取指定构造函数:type.GetConstructor();

参数:BindingFlags.Instance | BindingFlags.NonPublic

表示:实例构造函数 | private 构造函数

Type.EmptyTypes

无参数构造函数。

Invoke()

执行获取到的构造函数:

复制代码
constructor.Invoke(null)

六、为什么单例需要私有构造函数

单例设计目标:只能由内部创建,外部禁止创建

七、注意事项

  • 单例需要防止外部直接创建对象
  • 私有构造函数可以保证唯一性
  • 使用反射可以调用私有构造函数
  • 反射相比直接 new 有额外性能开销,但单例创建次数极少,影响可以忽略
  • 单例主要解决全局唯一对象管理问题,不应该所有类都使用
相关推荐
小羊没烦恼!21 小时前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
神仙别闹21 小时前
基于C#+MySQL实现(WinForm)个人聊天室软件
c#
伞伞悦读1 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
C语言小火车1 天前
C/C++ 为什么需要编译器?
开发语言·c++
霍霍的袁1 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
kybs19911 天前
全球灾害数据分析可视化 毕业设计-附源码66794
vue.js·spring boot·mysql·安全·django·c#·asp.net
孙启超1 天前
【AI开发之Rust】第 11 课:智能指针与内部可变性
开发语言·后端·rust
此生决int1 天前
深入理解C++系列(20)——C++11(下)
开发语言·c++
CoderYanger1 天前
A.每日一题:835. 图像重叠
java·开发语言·程序人生·leetcode·面试·职场和发展·学习方法
伞伞悦读1 天前
【第37期】Python JSON 与配置详解:序列化、反序列化、嵌套结构和配置文件
开发语言·python·json