C# Design – Creating Instances of an Interface Through a Static Method

cdesign

Is the following design flawed?

Basically I have a main class used to create an object of a type and then return it as the main interface of the type. The problem with this is that each of the classes that implement the interface all have different properties that need to be set. So I then have to cast them back to their main type to set them. See the below code:

public MainClass
{
    public static IInterface CreateInstance(InstanceType instanceType)
    {
        IInterface interface = null;
        switch (instanceType)
        {
            case InstanceType.ClassA:
            interface = new ClassA;
            break;

            case InstanceType.ClassB:
            interface = new ClassB;
            break;
        }

        return interface;
    }
}

public interface IInterface
{
    string Method1();
}

public class ClassA : IInterface
{
    public string Property1 { get; set; }

    public string Method1()
    {
        //...
    }
}

public class ClassB : IInterface
{
    public int Property2 { get; set; }

    public string Method1()
    {
        //...
    }
}

This is then used like:

IInterface interface = MainClass.CreateInstance(InstanceType.ClassA);
ClassA class = interface as ClassA;
class.Property1 = "";

interface.Method1();

Is there a better way to do this? (In reality there are more methods and properties than this)

Best Answer

The act of creating an instance like this is called a factory pattern. It's very common and has several advantages in some cases.

However, the main point of having a factory give you references to an abstract type (interface) is that the client code doesn't need to, nor should know about the different subtypes. The client is decoupled from both object creation and the classes themselves. This is lost when you downcast to ClassA in client code.

You still may reap some benefits of decoupling client code from object construction, but if you absolutely HAVE to downcast, then just make several methods on the factory instead (CreateClassA() : ClassA, CreateClassB() : ClassB, etc).

Try to avoid this though. Factories shine when they allow you to decouple completely from an object graph and just code to some common interface. If your factory is just a really convoluted way to call the constructor, then you will have gained nothing and added a lot of complexity.