除了“what is so bad about singletons”:-)之外,我还有一个ASP.NET Web应用程序,它在业务逻辑层使用单例,因此:
public class MyBusinessService
{
private static MyBusinessService mInstance = null;
public static MyBusinessService Instance
{
get { return mInstance; }
}
static MyBusinessService()
{
mInstance = new MyBusinessService();
}
}
我们主要将它们用于Model View Presenter架构中的依赖项。
它们还可以通过两种方式之一跨业务逻辑类使用。首先以下列方式:
var myService = new MyBusinessService();
myService.DoSomething();
myService.DoSomethingElse();
或者,它可以按以下方式使用:
MyBusinessService.Instance.DoSomething();
MyBusinessService.Instance.DoSomethingElse();
哪种结构首选,为什么?我对单身模式本身的好坏不感兴趣。
更新: 好吧,这个问题似乎很受欢迎。我猜这是一个准单身人士。最糟糕的是两个世界!我真的不想重构模式/反模式/代码地狱。我更感兴趣的是了解所描述的两种用法的影响。
我们的视图(ASP.NET页面)如下所示:
var presenter = new SomeViewPresenter(this, MyBusinessService.Instance);
但也可以实现为:
var presenter = new SomeViewPresenter(this, new MyBusinessService());
在这种情况下,我更喜欢前者。注:单词的使用和上面的错误用法是可以理解的,但是正如代码所示,这两个原始选项的结果是什么?
答案 0 :(得分:2)
您的班级不是没有私人构造函数的单身人士
所以如果你添加一个私有构造函数
private MyBusinessService()
{
}
然后你被限制在第二次使用,它是一个单身类
答案 1 :(得分:2)
后者是首选,因为前者的行为不像单身人士 - 你实例化一个新实例而没有任何保护来阻止多个实例存在。
如果你把这些警卫放在适当位置,后者就是你可能最终得到的代码。您也不需要一直使用该属性:
var service = MyBusinessService.Instance;
service.This();
service.That();
我也对ASP.NET中的静态有一些怀疑,这是来自WinForms开发人员: - )
答案 2 :(得分:1)
第一个可以说是首选,因为它不是单身人士。既然你想把关于单身人士的论点放在一边,那么第二个就是首选,因为它是。
答案 3 :(得分:1)
通常,只要您希望将程序限制为具有类的单个实例,就应该使用单例模式。应该使用它而不是简单地将所有内容标记为静态,因为当你这样做时,不可能将该类作为一个实例(例如将它作为参数传递给类/方法),这使得遵循良好的设计模式,如依赖性倒置原则很难或不可能。
你对MyBusinessService“新”起来的能力击败了单身人士的目的。如果您希望能够随意创建新实例,那么只需将其设为普通实例类即可。如果要限制为一个实例,那么根据定义,您不应该有权访问默认构造函数。
以下是您的课程看起来像真正的单身人士:
public class MyBusinessService
{
private static MyBusinessService mInstance = null;
public static MyBusinessService Instance
{
get { return mInstance; }
}
static MyBusinessService()
{
mInstance = new MyBusinessService();
}
private MyBusinessService() {}
}
添加标记为private的默认实例构造函数意味着var myService = new MyBusinessService();
不会从MyBusinessService范围之外编译(从而限制其用于静态构造函数)。
还有一件事;如果MyBusinessService可能不会在每种情况下都使用,或者创建起来很昂贵,那么你可能会考虑让它变得懒惰。默认情况下,静态构造函数在启动时运行;但是,静态成员在首次引用之前不会被评估。因此,您可以像这样设置您的类,并且在程序知道它需要一个之前不会创建MyBusinessService实例:
public class MyBusinessService
{
//the instantiation will not happen until the Instance property is called
private static readonly MyBusinessService mInstance = new MyBusinessService();
public static MyBusinessService Instance
{
get { return mInstance; }
}
private MyBusinessService() {}
}
答案 4 :(得分:0)
上面两个选项是完全不同的。第一个选项将调用默认的ctor,但第二个选项不会。这可能是也可能不是问题,具体取决于您是否需要初始化任何实例成员。
如果您不需要基于实例的ctor,我的偏好是选项#2。这真的取决于你如何使用它。
答案 5 :(得分:0)
在这两个选项中,第二个选项是首选的,因为它的行为类似于真正的单身人士。
有关如何实施单身人士的明确指南,请参阅http://csharpindepth.com/Articles/General/Singleton.aspx。
你会发现要记住几个方面(如性能,懒惰,异常,线程安全等)。