Confusione con il modello di fabbrica per quanto riguarda il principio di sostituzione di Liskov, la manutenibilità del codice e il test unitario?

4

Ho una certa confusione riguardo a Factory Pattern, ci sono fondamentalmente due modi per implementarli.

Metodo 1:

public interface IProductFactory
{
    IProduct GetProductA();
    IProduct GetProductB();
    IProduct GetProductC();
}

public class ProductFactory : IProductFactory
{
    public IProduct GetProductA()
    {
        //some implementation goes here
    }
    public IProduct GetProductB()
    {
        //some implementation goes here
    }
    public IProduct GetProductC()
    {
        //some implementation goes here
    }
}

Approccio 2:

public enum ProductType
{
    ProductA = 1,
    ProductB = 2,
    ProductC = 3
}

public interface IProductFactory
{
    IProduct GetProduct(ProductType productType);
}

public class ProductFactory : IProductFactory
{
    public IProduct GetProduct(ProductType productType)
    {
        switch (productType)
        {
            case ProductType.ProductA:
                //return IProduct with specific implementation
                break;
            case ProductType.ProductB:
                //return IProduct with specific implementation
                break;
            case ProductType.ProductC:
                //return IProduct with specific implementation
                break;
            default:
            //return null
        }
    }
}

Pro di entrambi gli approcci

Metodo 1:

    Il vantaggio di
  1. del tempo di compilazione verifica che la classe di implementazione sarà costretto a fornire i metodi corrispondenti.

Approccio 2:

  1. L'implementazione avrà il vantaggio di un numero inferiore. di linee di codice.
  2. L'interfaccia non diventa fragile, non cambierà come nuova i prodotti continuano ad aggiungere.

Contro entrambi gli approcci

Metodo 1:

  1. Le linee di codice diventano grandi.
  2. Man mano che viene implementato un numero maggiore di prodotti, l'interfaccia cambia e quindi è difficile seguire il principio di sostituzione di Liskov.

Approccio 2:

  1. Poiché nasconde i dettagli interni di GetProduct, è difficile dire cosa restituirà la Factory quando è presente un tipo specifico di enum passato.
  2. Potresti entrare in eccezioni di runtime

Sto ancora lottando per decidere quale approccio usare?

Nota: sono solo consapevole di questi due approcci, potrebbero esserci anche approcci diversi.     
posta shankbond 28.08.2013 - 06:56
fonte

2 risposte

4

Entrambi gli approcci infrangono il Principio di sostituzione di Liskov. L'implementazione corretta sembrerà smth. come:

public interface IProductFactory
{
    IProduct GetProduct();
}

public class Product1Factory : IProductFactory
{
    public IProduct GetProduct()
    {
        return new Product1(); //configure instance here
    }
}

public class Product2Factory : IProductFactory
{
    public IProduct GetProduct()
    {
        return new Product2(); //configure instance here
    }
}

public class Product3Factory : IProductFactory
{
    public IProduct GetProduct() //configure instance here
    {
        return new Product3();
    }
}
    
risposta data 28.08.2013 - 07:29
fonte
2

L'approccio 2 è il classico Modello di fabbrica . Questo modello non ha nulla a che fare con LSP. Per garantire che LSP non sia violato nei programmi client, è necessario progettare attentamente l'interfaccia IProduct in modo tale che il programma client che funziona su IProduct continui a funzionare senza alcuna modifica indipendentemente dal prodotto concreto che implementa effettivamente %codice%. Se osservi che stai violando LSP ridisegnare le interfacce.

Ad esempio, potrebbe essere meglio creare un'interfaccia per una categoria di prodotti se queste categorie differiscono nel modo in cui il client comunica con loro.

public interface IPerfume
{
    //Methods specific perfume products
}

public interface IAutomobile
{
    //Methods specific to automobiles
}

Quindi, si definisce una fabbrica per ogni categoria di prodotti. IProduct per creare prodotti profumati e PerfumeFactory per creare automobili.

L'esempio potrebbe non sembrare elaborato, ma è tutto ciò a cui riesco a pensare ora.

    
risposta data 29.08.2013 - 11:40
fonte