在我的项目中,我有多个“服务”静态类,应该可以在整个项目中轻松访问,因此它们是静态的。但是,为了初始化它们,我必须传递它们仅在启动时可用的数据,这导致代码类似于:
public static class VisualStudioEvents
{
private static Data _data;
public static void Initialize(Data data)
{
_data = data;
}
public static void Func()
{
AssertInitialized(_data);
// Code of actual Func() goes here.
}
}
你怎么看?这里应该应用不同的设计模式吗?或者这种设计是否可以接受?
谢谢!
答案 0 :(得分:5)
我对此非常满意。我所做的唯一改变就是将其强制执行一次:
public static void Initialize(Data data)
{
if (data == null) throw new ArgumentNullException("data");
if (Interlocked.CompareExchange(ref _data, data, null) != null)
{
throw new InvalidOperationException("Already initialized");
}
}
哦 - 我猜Data
也应该是不可变的,以避免人们意外更改配置。
答案 1 :(得分:4)
我强烈反对具有状态的静态类,它与全局变量没有区别,带有状态的静态类只是将全局变量包装到类中。并we all know why globals are bad。
我认为你应该得到某种inversion of control解决方案,这将允许你获得辅助类的非静态的,已初始化的实例。您的IoC容器可以在内部使用单例来确保使用单个配置对象。
例如,结构可能是:
public class VisualStudioEvents
{
public VisualStudioEvents(VisualStudioEventsConfig config)
{
// ...
}
// ...
}
在应用程序初始化时,您可以创建一个VisualStudioEventsConfig
实例,对其进行配置并添加到IoC容器中作为该类型的唯一实例。然后,将使用此准备好的配置实例初始化VisualStudioEvents
实例的每个调用。
答案 2 :(得分:3)
这可能是Singleton模式的一个很好的例子,您可以在构造函数中调用initialize,Data
作为类成员,如果Data
不可用则抛出异常。
但是,您问题中的Data
尽可能通用,因此根据其目的/可用性,可能有更好的方法来协调此初始化。
编辑
答案 3 :(得分:2)
名称VisualStudioEvents
似乎表明此类是代码与实际Visual Studio扩展API之间抽象的一部分。
如果这是正确的,那么你需要在单元测试中模拟VisualStudioEvents
。我根本不会把它变成静态类。 Static methods are death to testability
编辑:正如评论中所述,链接的博文可能过于激进。我个人认为静态方法只有在包含应该是component一部分的代码时才是邪恶的。将组件代码放在静态方法中会导致单元测试和依赖注入的static cling问题。
答案 4 :(得分:0)
您可以尝试使用singleton pattern而不是静态类。这样也可以更容易地测试代码。