C# – Creating multiple instances of an implementing class

abstract classcdesigninheritance

I currently have an abstract class and multiple classes extending it. My problem is, that there has to be a way to create a variable number of instances of an extending class. The number of instances depends on some results from a prior operation and on the extending class itself.

For now, there is just a method separated from the classes which creates the instances. That is bad, because I want to be able to add a new extending class without changing code somewhere else in the program.

One way of solving the problem might be declaring a static method in the abstract class and overwriting int the extending class. But this is a bit messy because static methods and the concept of abstract classes do not really work well together. Also, defining abstract static methods is not allowed, which makes sense.

How would you solve this problem? Maybe a Factory class per extending class?

Best Answer

Following the design patterns proposed by the Gang of Four, you can use the Abstract Factory pattern to instantiate the different implementations. For instance:

abstract class Parent {
   // some abstract behaviour
}

interface ParentFactory {
    Parent Make();
}

class Impl1 : Parent {
  // some concrete behaviour
}

class Impl1Factory : ParentFactory {
    public Parent Make() {
        return new Impl1();
    }
}

class Impl2 : Parent {
  // some concrete behaviour
}

class Impl2Factory : ParentFactory {
    public Parent Make() {
        return new Impl2();
    }
}

This will isolate the responsibilities of creating instances of each subtype to its own classes, which can be placed in different namespaces or even separate libraries, allowing you to make isolated changes whenever needed.

But just the abstract factory pattern by itself is not very friendly to use, so a common practice is to make some sort of registry, where the rest of the system can query for a specific implementation. An example of that would be to use something similar to the Service Locator pattern, like so:

class ParentFactories {
    private Dictionary<string, ParentFactory> factories;

    // constructor and such - probably private and following the Singleton pattern

    public void Register(string key, ParentFactory factory) {
        factories.Add(key, factory);
    }

    public Parent Make(string key) {
        return dictionary[key].Make();
    }
}

In the above example, I used a string for the key, but that was just to show how to register a factory in the locator using a Dictionary, which is the common approach. You can use anything that is relevant to your business rules, including your own objects as some sort of identifier/query object that tells the locator which implemention is required.

Anyway, the point of a Locator-like object is to allow the system to add and/or remove different implementation os the ParentFactory at runtime. Following this pattern, you can separate the concrete implementations of your abstract class into different modules of the application, and have each module register its implementations on the locator at boot-up.