Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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. Now Class B (which itself will be available as a singleton as is Class A) needs its own library instance...

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.

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.

like image 875
Dunken Avatar asked Feb 22 '23 17:02

Dunken


1 Answers

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.

Singletons are useful for certain cases like Logging, however they are generally avoided as they are notoriously difficult to mock out, test and extend.

If possible, I would recommend refactoring the above code to use the Inversion of Control Pattern and constructor injection of the dependency. This is achieved by creating an interface, say ILibrary and having two implementations.

These implementations can be created once and stored to emulate Singleton-like behaviour in a third helper class. 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.

A code example using IoC/DI as a pattern would look like this:

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();
}
like image 88
Dr. Andrew Burnett-Thompson Avatar answered Feb 28 '23 03:02

Dr. Andrew Burnett-Thompson