Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在OOP中使用可选的单例?_C#_Oop_Design Patterns_Singleton - Fatal编程技术网

C# 在OOP中使用可选的单例?

C# 在OOP中使用可选的单例?,c#,oop,design-patterns,singleton,C#,Oop,Design Patterns,Singleton,我正在.NET中编写一个PCL,在HttpClient周围有一个包装器类,它以多种不同的方法从URI加载HtmlAgilityPack.HtmlDocument。它是无状态的,所以我真的希望它是静态的,因为在我看来,用new实例化某个东西给人的印象是它包含状态。然而,我有几个接口,我希望它从中继承,所以它不能是静态的。这就是我想让它成为单身汉的地方。以下是代码中的一些片段: public class ConcurrentClient : IAsyncClient<HtmlDocument&

我正在.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)
    {
        // ...
    }
}
原因是我不太确定是否使用Singleton模式,主要是因为我很少在其他库中使用它(可能是WinRT的
应用程序.Current
?),我认为这会鼓励我的PCL用户编写耦合代码,因为到处调用
ConcurrentClient.Instance
要比作为参数传入容易得多


然而,我确实希望鼓励使用共享实例,因为排除上述原因,调用
new ConcurrentClient()
没有什么意义,因为它只会产生更多的内存开销。另外,我想不出更好的方法来使用不真正依赖于状态的方法实现继承。

您的单例已经实现了2个接口。真正的问题是,这个单例的依赖关系在哪里?它们为什么在那里?
如果答案是这些依赖关系存在是因为它们需要实现这些接口,那么我会说这是错误的
做一个可靠的设计的全部要点是依赖于接口,而不是任何具体的实现。因此,任何需要这两个接口中任何一个的人都应该通过依赖项注入获得这些接口。这意味着接口将由其构造函数传递,或通过方法调用、策略模式中的额外参数传递

另请参见:

这可能是一个单身的理由,但根据你的解释,这不是很清楚

在使用依赖项注入方面花更多的时间进行调查。如果您已经控制了它,请进一步研究如何使用控制反转容器

另外,当您可以通过Singleton.Instance访问对象时,很容易忘记DI并将其作为参数传递

您忘记了单元测试。如果将接口传递给类构造函数,则可以轻松地模拟这些接口并测试类功能。有了你的单例,你的类真的需要这个单例。单元测试将更加困难。
当然,实例是很容易访问的,它是一个全球性的,因为人们总是回到对对象编程的旧习惯,这就是为什么它如此流行的原因。

您有一个陷阱:您使用的是单例。更好的办法是解释你真正的问题以及为什么你认为使用单例是解决方案,我们可能会向你推荐一些不同的东西。我看不到任何澄清。真正需要解决的问题或用例是什么?为什么你认为使用单例可以解决这个问题?为什么不对有状态但不可变的类使用不同的设计来保证设计线程的安全呢?如果有公共构造函数,它根本就不是单例。是的,您有一个公开可用的共享实例,但您并没有阻止创建其他实例,所以我就不谈了。不要管它叫单例。是否有公共构造函数根本不是OP的问题,他只是问单例作为一种模式是否是一个好的选择。如果我们说它是好的,我相信他会将构造函数私有化,并使其成为一个合适的单例。在我的库的其余部分中,没有对单例的依赖,它是供公众使用的。当/如果我以后在其上构建时,我计划做的是只引用它一次,然后将它作为接口参数传递给我的其他方法。此外,我想你可能误解了我文章的最后一部分(在编辑之前):我是在暗示我对使用单例的恐惧,而不是说“是的,好吧,让我们拧DI,让我们的代码完全无法维护“我还是不明白你为什么需要一个单身汉,你需要一个IOC容器。您只需注册一次接口。每次需要解析依赖于先前注入的接口的另一个接口时,IOC都会处理注入。这是否意味着新实例或相同实例可以在IOC容器中配置。
private static readonly ConcurrentClient _SharedInstance = new ConcurrentClient();

public static ConcurrentClient SharedInstance
{
    get { return _SharedInstance; }
}