简体   繁体   English

需要两个单身实例

[英]Two instances of a singleton needed

I had to extend my existing code with a Class B. The existing code uses a singleton in Library. 我不得不用B类扩展现有代码。现有代码在Library中使用单例。 Now Class B (which itself will be available as a singleton as is Class A) needs its own library instance... 现在,B类(它本身将作为A类单独使用)需要自己的库实例......

I'm wondering what's the best way to extend the existing code (Class A, Library) such that I have to change the library as less as possible. 我想知道扩展现有代码(A类,库)的最佳方法是什么,这样我就必须尽可能少地更改库。

public class A 
{
    var lib = Library.Instance;

    public DoSomething()
    {
        lib.DoStuff();
    }    
}

public class B
{
    var lib = Library.Instance;  //wrong! needs its own instance

    public DoSomething()
    {
        lib.DoOtherStuff();
    }    
}

public class Library
{
    public static Library Instance
    {
        get
        {
            return _librarySingleton;
        }
    }

    //library internally uses singleton too!!
}

public static class MyProgram
{
    var a = new A();    //will be an singleton
    var b = new B();    //will be an singleton

    a.DoSomething();
    b.DoSomething();
}

There will never be another class. 永远不会有另一个班级。 So two instances will be just fine. 所以两个实例就可以了。

Unfortunately the Singleton pattern really can't help you here as this pattern is specifically designed to return one and only one instance for the lifetime of the application. 不幸的是, Singleton模式实际上无法帮助您,因为此模式专门设计为在应用程序的生命周期内返回一个且仅一个实例。

Singletons are useful for certain cases like Logging, however they are generally avoided as they are notoriously difficult to mock out, test and extend. 单身对于某些情况如Logging非常有用,但是它们通常被避免,因为它们很难被模拟,测试和扩展。

If possible, I would recommend refactoring the above code to use the Inversion of Control Pattern and constructor injection of the dependency. 如果可能的话,我建议重构上面的代码以使用Inversion of Control Pattern和构造函数注入依赖项。 This is achieved by creating an interface, say ILibrary and having two implementations. 这是通过创建一个接口来实现的,例如ILibrary并具有两个实现。

These implementations can be created once and stored to emulate Singleton-like behaviour in a third helper class. 这些实现可以创建一次并存储,以在第三个辅助类中模拟类似Singleton的行为 A really good way of doing this is in an enterprise application is to utilise a Dependency Injection Container , which maintains the lifetime of instances (Singleton or Transient) and allows easy injection into constructors. 一个非常好的方法是在企业应用程序中使用依赖注入容器 ,它维护实例的生命周期(Singleton或Transient)并允许轻松注入构造函数。

A code example using IoC/DI as a pattern would look like this: 使用IoC / DI作为模式的代码示例如下所示:

public class A 
{
    private readonly ILibrary _library;

    public A(ILibrary library)
    {
        _library = library;
    }

    public DoSomething()
    {
        _library.DoStuff();
    }    
}

public class B
{
    private readonly ILibrary _library;

    public B(ILibrary library)
    {
        _library = library;
    }

    public DoSomething()
    {
        _library.DoStuff();
    }      
}

public interface ILibrary
{
    void DoStuff();
}

public class LibraryTypeOne : ILibrary
{
    void DoStuff()
    {
         Console.WriteLine("I am library type one");
    }
}

public class LibraryTypeTwo : ILibrary
{
    void DoStuff()
    {
         Console.WriteLine("I am library type two");
    }
}

public static class MyProgram
{
    var a = new A(new LibraryTypeOne());    // Note, you need to store
    var b = new B(new LibraryTypeTwo());    // these instances somewhere to 
                                            // share throughout the app

    a.DoSomething();
    b.DoSomething();
}

If your design will always be limited to 2 instances, you could provide a property Library.SecondInstance . 如果您的设计始终限制为2个实例,则可以提供属性Library.SecondInstance

Anyway, you might want to take a look at the Multiton pattern as well. 无论如何,你可能也想看看Multiton模式。

DI container comes in very handy in these cases. DI容器在这些情况下非常方便。 Both A and B have a dependency on Libraray instance. A和B都依赖于Libraray实例。 Instead of creating that instance in those two classes, inject the dependency in to them. 不是在这两个类中创建该实例,而是将依赖项注入其中。 DI containers like Autofac maintain the single instance life time for you thus allowing you to inject these dependencies freely. 像Autofac这样的DI容器可以为您保持单个实例的生命周期,从而允许您自由地注入这些依赖项。

 public class Library
    {
        public Library()
        { }
        private static Library _secondInstance = new Library();
        private static Library _librarySingleton = new Library();
        public Library Second()
        {
            return _secondInstance;
        }
        public static Library Instance
        {
            get
            {
                return _librarySingleton;
            }
        }
        //library internally uses singleton too!!
    }

usage 用法

 Library obj1 = Library.Instance;
 Library obj2= Library.Instance.Second();

Looks a bit readable to me 看起来对我来说有点可读

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM