非常直截了当的问题。
什么是单身人士,何时应该使用它?
答案 0 :(得分:128)
单例是一个只允许创建自己的一个实例的类 - 并且可以简单,轻松地访问所述实例。单例前提是跨软件开发的模式。
有一个C#实现"Implementing the Singleton Pattern in C#"涵盖了你需要知道的大部分内容 - 包括一些关于线程安全的好建议。
说实话,你需要实现一个单例是非常罕见的 - 在我看来,它应该是你应该注意的事情之一,即使它不经常使用。
答案 1 :(得分:48)
你问过C#。琐碎的例子:
public class Singleton
{
private Singleton()
{
// Prevent outside instantiation
}
private static readonly Singleton _singleton = new Singleton();
public static Singleton GetSingleton()
{
return _singleton;
}
}
答案 2 :(得分:39)
它是什么:在应用程序的生命周期中只有一个持久实例的类。请参阅Singleton Pattern。
何时应该使用它尽可能少。只有当你完全确定时才需要它。我不愿意说“从不”,但通常有一个更好的选择,例如依赖注入或简单的静态类。
答案 3 :(得分:24)
在c#中实现单例的另一种方法,我个人更喜欢这种方式,因为你可以将singeton类的实例作为属性而不是方法来访问。
public class Singleton
{
private static Singleton instance;
private Singleton() { }
public static Singleton Instance
{
get
{
if (instance == null)
instance = new Singleton();
return instance;
}
}
//instance methods
}
但是,据我所知,这两种方式都被认为是对的'所以它只是个人风格。
答案 4 :(得分:10)
using System;
using System.Collections.Generic;
class MainApp
{
static void Main()
{
LoadBalancer oldbalancer = null;
for (int i = 0; i < 15; i++)
{
LoadBalancer balancerNew = LoadBalancer.GetLoadBalancer();
if (oldbalancer == balancerNew && oldbalancer != null)
{
Console.WriteLine("{0} SameInstance {1}", oldbalancer.Server, balancerNew.Server);
}
oldbalancer = balancerNew;
}
Console.ReadKey();
}
}
class LoadBalancer
{
private static LoadBalancer _instance;
private List<string> _servers = new List<string>();
private Random _random = new Random();
private static object syncLock = new object();
private LoadBalancer()
{
_servers.Add("ServerI");
_servers.Add("ServerII");
_servers.Add("ServerIII");
_servers.Add("ServerIV");
_servers.Add("ServerV");
}
public static LoadBalancer GetLoadBalancer()
{
if (_instance == null)
{
lock (syncLock)
{
if (_instance == null)
{
_instance = new LoadBalancer();
}
}
}
return _instance;
}
public string Server
{
get
{
int r = _random.Next(_servers.Count);
return _servers[r].ToString();
}
}
}
我从dofactory.com获取了代码,没有那么花哨但是我发现这远远比Foo和Bar 更好的例子来自Judith Bishop关于C#3.0的设计模式有关于活动应用程序的示例在mac dock。
如果查看代码,我们实际上是在 for 循环上构建新对象,这样就可以创建新对象但重用实例,因为oldbalancer和newbalancer具有相同的实例,如何?由于 GetLoadBalancer()上使用了 static 关键字,尽管服务器值不同是随机列表,但 GetLoadBalancer()上的静态属于类型本身而不是特定对象。
if (_instance == null)
{
lock (syncLock)
{
if (_instance == null)
来自MSDN
lock关键字确保一个线程不进入代码的关键部分,而另一个线程处于临界区。如果另一个线程试图输入一个锁定的代码,它将等待,阻塞,直到该对象被释放。
所以每次都会发出互斥锁,即使它不需要也不需要,所以我们进行空检查。
希望它有助于清理更多。
如果我的理解是指导错误的方式,请发表评论。
答案 5 :(得分:6)
Singleton(这与C#无关,它是一种OO设计模式)是您希望在整个应用程序中只允许创建一个类的一个实例。使用通常包括全球资源,虽然我会从个人经验中说,但它们往往是巨大痛苦的根源。
答案 6 :(得分:5)
虽然只能有一个单例的实例,但它与静态类不同。静态类只能包含静态方法,并且永远不能实例化,而单例的实例可以与任何其他对象一样使用。
答案 7 :(得分:2)
这是一种设计模式,并不是特定于c#。更多关于互联网和SO的内容,例如wikipedia article。
在软件工程中,单身人士 模式是一种设计模式 用来限制a的实例化 类到一个对象。这很有用 什么时候只需要一个对象 协调整个系统的行动。 这个概念有时会被概括 到运行更多的系统 只有一个对象时有效 存在,或限制 实例化到一定数量的 对象(比如说五个)。有些人认为 反模式,判断它是 过度使用,引入不必要的 鞋底情况的局限性 实际上并不是一个类的实例 要求,并介绍全球状态 进入申请表。
如果你想要一个只能实例化一次的课程,你应该使用它。
答案 8 :(得分:2)
我用它来查找数据。从DB加载一次。
public sealed class APILookup
{
private static readonly APILookup _instance = new APILookup();
private Dictionary<string, int> _lookup;
private APILookup()
{
try
{
_lookup = Utility.GetLookup();
}
catch { }
}
static APILookup()
{
}
public static APILookup Instance
{
get
{
return _instance;
}
}
public Dictionary<string, int> GetLookup()
{
return _lookup;
}
}
答案 9 :(得分:2)
什么是单身人士:
它是一个只允许创建自己的一个实例的类,并且通常可以简单地访问该实例。
您应该何时使用:
这取决于具体情况。
注意:请不要在数据库连接上使用,请详细解答refer @Chad Grant的答案
以下是Singleton
的简单示例:
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
您还可以使用Lazy<T>
创建Singleton
。
See here了解使用Lazy<T>
答案 10 :(得分:1)
以下是单身人士:http://en.wikipedia.org/wiki/Singleton_pattern
我不知道C#,但实际上它在所有语言中都是一样的,只是实现方式不同。
一般情况下,你应该尽可能避免使用单身人士,但在某些情况下,这是非常方便的。
对不起我的英文;)
答案 11 :(得分:1)
Singleton类用于为整个应用程序域创建单个实例。
public class Singleton
{
private static Singleton singletonInstance = CreateSingleton();
private Singleton()
{
}
private static Singleton CreateSingleton()
{
if (singletonInstance == null)
{
singletonInstance = new Singleton();
}
return singletonInstance;
}
public static Singleton Instance
{
get { return singletonInstance; }
}
}
在 this article it is described 中我们如何使用readonly变量创建线程安全的单例类及其在应用程序中的实际用途。
答案 12 :(得分:1)
不使用锁也没有延迟实例化的线程安全单例。
此实现具有静态构造函数,因此每个应用程序域仅执行一次。
public sealed class Singleton
{
static Singleton(){}
private Singleton(){}
public static Singleton Instance { get; } = new Singleton();
}
答案 13 :(得分:0)
E.X您可以将Singleton用于需要注入的全局信息。
就我而言,我将Logged用户的详细信息(用户名,权限等)保留在Global Static Class中。当我尝试实现单元测试时,我无法将依赖项注入Controller类。因此,我将我的静态类更改为单例模式。
public class SysManager
{
private static readonly SysManager_instance = new SysManager();
static SysManager() {}
private SysManager(){}
public static SysManager Instance
{
get {return _instance;}
}
}
http://csharpindepth.com/Articles/General/Singleton.aspx#cctor
答案 14 :(得分:0)
我知道回答这个问题已经很晚了,但是使用自动属性,您可以执行以下操作:
public static Singleton Instance { get; } = new Singleton();
您在Singleton
上课的地方并且可以通过,在这种情况下,它是只读属性Instance
。
答案 15 :(得分:0)
当我们需要确保仅创建特定类的一个实例,然后为整个应用程序提供对该实例的简单全局访问时,我们需要在C#中使用Singleton设计模式。
可以使用Singleton设计模式的实时方案: 服务代理:众所周知,调用服务API是应用程序中的一项广泛操作。花费大部分时间的过程是创建服务客户端以调用服务API。如果将服务代理创建为Singleton,则它将提高应用程序的性能。
外观:您也可以将数据库连接创建为Singleton,以提高应用程序的性能。
日志:在应用程序中,对文件执行I / O操作是一项昂贵的操作。如果您将Logger创建为Singleton,则它将提高I / O操作的性能。
数据共享:如果您有任何常量值或配置值,则可以将这些值保留在Singleton中,以便应用程序的其他组件可以读取它们。
缓存:众所周知,从数据库中获取数据是一个耗时的过程。在您的应用程序中,您可以将主服务器和配置缓存在内存中,这将避免DB调用。在这种情况下,可以使用Singleton类以有效的方式处理具有线程同步的缓存,从而大大提高应用程序的性能。
C#中单例设计模式的缺点 在C#中使用Singleton设计模式的缺点如下:
单元测试非常困难,因为它将全局状态引入到应用程序中。 它减少了程序内并行的可能性,因为要在多线程环境中访问单例实例,您需要使用锁定来序列化对象。
我从下面的文章中引用了这一点。
https://dotnettutorials.net/lesson/singleton-design-pattern/