Creazione di istanze di un'interfaccia tramite un metodo statico

3

Il seguente disegno è difettoso?

Fondamentalmente ho una classe principale utilizzata per creare un oggetto di un tipo e quindi restituirlo come l'interfaccia principale del tipo. Il problema con questo è che ognuna delle classi che implementano l'interfaccia hanno tutte proprietà differenti che devono essere impostate. Quindi devo quindi restituirli al loro tipo principale per impostarli. Vedi il seguente codice:

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()
    {
        //...
    }
}

Viene quindi utilizzato come:

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

interface.Method1();

C'è un modo migliore per farlo? (In realtà ci sono più metodi e proprietà di questo)

    
posta TheLethalCoder 08.06.2016 - 12:55
fonte

2 risposte

6

L'atto di creare un'istanza come questa si chiama modello di fabbrica. È molto comune e presenta alcuni vantaggi in alcuni casi.

Tuttavia, il punto principale per cui una factory ti fornisce riferimenti a un tipo astratto (interfaccia) è che il codice client non è necessario, né deve conoscere i diversi sottotipi. Il client è disaccoppiato dalla creazione dell'oggetto e dalle classi stesse. Questo viene perso quando riduci a ClassA nel codice client.

Potresti ancora trarre alcuni vantaggi dal disaccoppiare il codice client dalla costruzione di un oggetto, ma se hai assolutamente bisogno di downcast, allora fai solo diversi metodi in fabbrica ( CreateClassA() : ClassA , CreateClassB() : ClassB , ecc.)

Cerca di evitare questo però. Le fabbriche brillano quando ti permettono di disaccoppiare completamente da un grafo di oggetti e di codificare semplicemente su un'interfaccia comune. Se la tua fabbrica è solo un modo complicato di chiamare il costruttore, allora non avrai guadagnato nulla e avrai aggiunto un sacco di complessità.

    
risposta data 08.06.2016 - 13:04
fonte
1

Come alternativa a fornire un valore dall'enum InstanceType come argomento per cambiare il tipo di oggetto da costruire, potresti fornire un parametro di tipo generico e usare quel parametro come tipo di ritorno. Per esempio:.

class MainClass
{
    public static T CreateInstance<T>()
        where T: IInterface
    {
        // ...
    }
 }

Puoi mantenere l'istruzione switch in CreateInstance (in realtà sostituita da una sequenza di if -statements) oppure puoi utilizzare un campo statico in una classe generica come tipo di tabella di ricerca:

class BuilderClass<T>
    where T: IInterface
{
    static readonly Func<T> _construct;

    // Initialise '_construct' for each type you want to build from the static Constructor.
    static BuilderClass()
    {
        if (typeof(T) == typeof(ClassA))
        {
            BuilderClass<ClassA>._construct = () => new ClassA();
        }
        else if (typeof(T) == typeof(ClassB))
        {
            BuilderClass<ClassB>._construct = () => new ClassB();
        }
        else
        {
            BuilderClass<T>._construct = null;
        }
    }
}

CreateInstance può chiamare BuilderClass<T>._construct() :

public static T CreateInstance<T>()
    where T: IInterface
{
    System.Diagnostics.Debug.Assert(
        BuilderClass<T>._construct != null,
        $"Cannot not build objects of type {typeof(T).Name}");
    return BuilderClass<T>._construct();
}

Ma dovresti ancora pensare a kai answer e se è necessario impostare le proprietà specifiche del tipo, dopo aver creato IInterface -oggetti.

    
risposta data 08.06.2016 - 14:52
fonte

Leggi altre domande sui tag