单例模式(Singleton Pattern)是设计模式中最基础但应用最广泛的一种模式,它确保一个类只有一个实例,并提供一个全局访问点。在C#开发中,单例模式常用于管理共享资源、配置管理、日志系统等场景。
public class BasicSingleton
{
private static BasicSingleton _instance;
// 私有构造函数防止外部实例化
private BasicSingleton()
{
// 初始化代码
}
public static BasicSingleton Instance
{
get
{
if (_instance == null)
{
_instance = new BasicSingleton();
}
return _instance;
}
}
public void DoWork()
{
Console.WriteLine("单例工作方法");
}
}
// 使用示例
var singleton = BasicSingleton.Instance;
singleton.DoWork();
问题分析:此实现在多线程环境下可能创建多个实例,不适用于生产环境。
public class ThreadSafeSingleton
{
private static volatile ThreadSafeSingleton _instance;
private static readonly object _lock = new object();
private ThreadSafeSingleton() { }
public static ThreadSafeSingleton Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
{
_instance = new ThreadSafeSingleton();
}
}
}
return _instance;
}
}
}
关键点:
volatile
关键字确保多线程环境下的可见性public class LazySingleton
{
private static readonly Lazy<LazySingleton> _lazy =
new Lazy<LazySingleton>(() => new LazySingleton());
private LazySingleton() { }
public static LazySingleton Instance => _lazy.Value;
}
优势:
public class ReflectionSafeSingleton
{
private static readonly Lazy<ReflectionSafeSingleton> _lazy =
new Lazy<ReflectionSafeSingleton>(() => new ReflectionSafeSingleton());
private static bool _created;
private ReflectionSafeSingleton()
{
if (_created)
{
throw new InvalidOperationException("只能创建一个实例");
}
_created = true;
}
public static ReflectionSafeSingleton Instance => _lazy.Value;
}
[Serializable]
public class SerializableSingleton : ISerializable
{
private static readonly Lazy<SerializableSingleton> _lazy =
new Lazy<SerializableSingleton>(() => new SerializableSingleton());
private SerializableSingleton() { }
public static SerializableSingleton Instance => _lazy.Value;
// 防止序列化创建新实例
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
throw new NotSupportedException();
}
// 使用序列化代理
[Serializable]
private class SingletonSerializationHelper : IObjectReference
{
public object GetRealObject(StreamingContext context)
{
return SerializableSingleton.Instance;
}
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfigService, ConfigService>();
}
public class ConfigService : IConfigService
{
private readonly IConfiguration _config;
public ConfigService(IConfiguration config)
{
_config = config;
}
public string GetValue(string key)
{
return _config[key];
}
}
public class Multiton
{
private static readonly Dictionary<string, Lazy<Multiton>> _instances =
new Dictionary<string, Lazy<Multiton>>();
private static readonly object _lock = new object();
private Multiton(string key)
{
Key = key;
}
public string Key { get; }
public static Multiton GetInstance(string key)
{
if (!_instances.ContainsKey(key))
{
lock (_lock)
{
if (!_instances.ContainsKey(key))
{
_instances[key] = new Lazy<Multiton>(() => new Multiton(key));
}
}
}
return _instances[key].Value;
}
}
public class ThreadSingleton
{
private static readonly ThreadLocal<ThreadSingleton> _threadInstance =
new ThreadLocal<ThreadSingleton>(() => new ThreadSingleton());
private ThreadSingleton() { }
public static ThreadSingleton Instance => _threadInstance.Value;
}
实现方式 | 首次访问时间 | 后续访问时间 | 线程安全 |
---|---|---|---|
基础实现 | 快 | 快 | 否 |
双重检查锁定 | 中等 | 快 | 是 |
Lazy | 中等 | 极快 | 是 |
静态初始化 | 慢 | 极快 | 是 |
public class ConfigManager
{
private static readonly Lazy<ConfigManager> _instance =
new Lazy<ConfigManager>(() => new ConfigManager());
private readonly IConfiguration _config;
private ConfigManager()
{
_config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
}
public static ConfigManager Instance => _instance.Value;
public string GetSetting(string key) => _config[key];
}
public class Logger
{
private static readonly Lazy<Logger> _instance =
new Lazy<Logger>(() => new Logger());
private readonly StreamWriter _logWriter;
private Logger()
{
_logWriter = new StreamWriter("application.log", append: true);
}
public static Logger Instance => _instance.Value;
public void Log(string message)
{
_logWriter.WriteLine($"{DateTime.Now}: {message}");
_logWriter.Flush();
}
~Logger()
{
_logWriter?.Dispose();
}
}
public class CacheManager
{
private static readonly Lazy<CacheManager> _instance =
new Lazy<CacheManager>(() => new CacheManager());
private readonly ConcurrentDictionary<string, object> _cache =
new ConcurrentDictionary<string, object>();
private CacheManager() { }
public static CacheManager Instance => _instance.Value;
public T Get<T>(string key) where T : class
{
return _cache.TryGetValue(key, out var value) ? value as T : null;
}
public void Set(string key, object value, TimeSpan? expiry = null)
{
_cache[key] = value;
if (expiry.HasValue)
{
Task.Delay(expiry.Value).ContinueWith(_ => _cache.TryRemove(key, out _));
}
}
}
问题:在长时间运行的应用程序中,单例可能持有资源导致内存泄漏
解决方案:
public class DisposableSingleton : IDisposable
{
private static readonly Lazy<DisposableSingleton> _instance =
new Lazy<DisposableSingleton>(() => new DisposableSingleton());
private DisposableSingleton() { }
public static DisposableSingleton Instance => _instance.Value;
private bool _disposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
// 释放托管资源
}
// 释放非托管资源
_disposed = true;
}
~DisposableSingleton() => Dispose(false);
}
问题:单例的全局状态使单元测试困难
解决方案:使用接口和依赖注入
public interface ISingletonService
{
void PerformOperation();
}
public class SingletonService : ISingletonService
{
private static readonly Lazy<SingletonService> _instance =
new Lazy<SingletonService>(() => new SingletonService());
private SingletonService() { }
public static ISingletonService Instance => _instance.Value;
public void PerformOperation()
{
// 实现
}
}
// 测试中使用Mock
public class MyTest
{
[Fact]
public void TestMethod()
{
var mockService = new Mock<ISingletonService>();
var myClass = new MyClass(mockService.Object);
// 测试逻辑
}
}
在分布式系统中,单例模式演变为:
// 使用Azure Durable Functions实现分布式单例
[FunctionName("SingletonOrchestrator")]
public static async Task RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
// 确保只有一个实例运行
using (await context.LockAsync("mySingletonLock"))
{
// 单例业务逻辑
await context.CallActivityAsync("SingletonTask", null);
}
}
单例模式是C#开发中不可或缺的设计模式,但需要谨慎使用:
“单例模式就像一把双刃剑——用得好能简化架构,用不好会制造麻烦。理解其原理和应用场景,才能发挥它的真正价值。”