我在.NET中编写PCL,我有一个围绕HttpClient
的包装类,它以多种不同的方法从URI加载HtmlAgilityPack.HtmlDocument
。它是无状态,所以我真的想把它变成静态的,因为在我看来用new
实例化的东西给人的印象是它包含状态。但是,我有几个接口,我希望它继承,所以它不能是静态的。这就是我想把它变成单身人士的地方。以下是代码中的几个片段:
public class ConcurrentClient : IAsyncClient<HtmlDocument>
{
private static readonly ConcurrentClient _Instance = new ConcurrentClient();
private ConcurrentClient() { }
public static ConcurrentClient Instance
{
get { return _Instance; }
}
public HtmlDocument LoadUri(string uri)
{
return LoadUriAsync(uri).Result;
}
// ...
public async Task<HtmlDocument> LoadUriAsync(string uri,
Encoding e, NetworkCredential creds, Action<HtmlDocument> prehandler)
{
// ...
}
}
我想知道,如果我应该将开头的部分更改为:
private static readonly ConcurrentClient _SharedInstance = new ConcurrentClient();
public static ConcurrentClient SharedInstance
{
get { return _SharedInstance; }
}
原因是我对使用Singleton模式不太确定,主要是因为我很少看到它在其他库中使用过(可能是WinRT&#39; s Application.Current
? ),我认为它会鼓励我的PCL用户编写耦合代码,因为在任何地方调用ConcurrentClient.Instance
比将其作为参数传递更容易。
但是,我确实希望鼓励使用共享实例,因为排除上述原因,调用new ConcurrentClient()
时没有什么意义,因为它只是创建更多内存开销。另外,我无法想出一种更好的方法来实现继承,而不是真正依赖于状态的方法。
答案 0 :(得分:2)
你的Singleton已经实现了2个接口。真正的问题是,这个Singleton的依赖关系在哪里?为什么它们在那里?
如果答案是这些依赖关系存在,因为他们需要实现那些接口,那么我会说这是错误的。
执行SOLID设计的重点是依赖于接口而不是任何具体实现。因此,任何需要这两个接口中任何一个的人都应该通过依赖注入来获得这些接口。这意味着接口将由它们的构造函数传递,或者通过方法调用中的额外参数传递,策略模式,......
另见:http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx
可能有理由制作一个单身人士,但根据你的解释,这并不是那么清楚。
调查您使用依赖注入的更多时间。如果你掌握了控制权,那就进一步调查你如何使用控制容器的反转。
此外,当您可以通过Singleton.Instance访问它时,很容易忘记DI并将对象作为参数传递。
您忘记了单元测试。如果将接口传递给类构造函数,则可以轻松地模拟这些接口并测试类的功能。有了你的单身人士,你的班级真的需要那个单身人士。单元测试会更难。 当然Instance很容易访问,它是一个全球性的,因为人们一直回归到对象的旧编程习惯,这就是它如此受欢迎的原因。