Differenza tra la composizione di fabbrica e l'ereditare

3

Sto leggendo sul modello di progettazione "metodo di fabbrica" da "Head First Design Patterns". Quindi, c'è una classe

public class PizzaStore {
    SimplePizzaFactory factory;
    public PizzaStore(SimplePizzaFactory factory) {
        this.factory = factory;
    }
    public Pizza orderPizza(String type) {
        Pizza pizza;
        pizza = factory.createPizza(type);
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
}

Come puoi vedere sopra, memorizziamo factory e quindi chiamiamo createPizza(String) virtual function e chiameremo la funzione createPizza(...) appropriata per la classe factory concrete, ad esempio NYStylePizzaFactory o ChicagoStylePizzaFactory .    Ma poi l'autore continua:

But you’d like a little more quality control...!

e apporta le seguenti modifiche al codice:

public abstract class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza;
        pizza = createPizza();
        pizza.prepare();
        pizza.bake();
        pizza.cut();
        pizza.box();
        return pizza;
    }
    abstract Pizza createPizza();
}

public class NYStylePizzaStore : PizzaStore {
    Pizza createPizza() {
        return new NYStylePizza();
    }
}

public class ChicagoStylePizzaStore : PizzaStore {
    Pizza createPizza() {
        return new ChicagoStylePizza();
    }
}

Quindi, non capisco perché otteniamo più controllo di qualità in quest'ultimo caso? Sembra che il risultato sia lo stesso: viene chiamata la funzione virtuale appropriata.

    
posta David Hovsepyan 22.09.2017 - 17:13
fonte

2 risposte

1

Non ho il libro ma ho trovato alcuni fantastici diapositive su questo argomento. Assumerò che le diapositive seguono il libro. Sembrano confermare la mia ipotesi iniziale che si tratta di controllo sulla creazione di pizza.

Nel primo esempio lo store delega la creazione della pizza alla fabbrica, che viene iniettata dall'esterno dal codice di creazione. Il negozio stesso non ha voce in capitolo su come vengono create le pizze, le chiede solo alla fabbrica.

Nel secondo esempio lo store controlla la creazione della pizza tramite createPizza .

Ora chiedi "[i] non è logico che la fabbrica di cemento crei una pizza e non il negozio?"?

Si noti che nel secondo esempio abbiamo anche una fabbrica, solo che è un metodo invece di un oggetto. Quindi permettimi di riformulare la domanda:

Non è più logico utilizzare una fabbrica iniettata invece di un metodo di fabbrica?

Forse è così. Le mie diapositive suggeriscono che il franchisor vuole dare ai negozi il controllo sulla creazione di pizze mantenendo il controllo sulla preparazione degli ordini, il che ha senso, e il bit sul controllo di qualità sembra riferirsi a questo.

Ma da lì salta a "ciò che ti piacerebbe davvero fare è creare un framework che leghi il negozio e la creazione della pizza insieme" e non riesco a capire perché.

È vero che una classe base astratta che implementa orderPizza e sottoclassi che implementano createPizza è il modello più diretto di quanto sopra e questo dà all'autore una buona scusa per introdurre il modello di fabbrica. Ma la mappa non è il territorio e i progettisti di software hanno preoccupazioni diverse rispetto ai franchisor e ai franchisee di negozi di pizza. Non è necessariamente vero che il modello più diretto è il migliore e il controllo nel mondo reale non è lo stesso del controllo nel software OO.

    
risposta data 22.09.2017 - 20:12
fonte
7

È una differenza tra il controllo della correttezza di qualcosa in fase di esecuzione (esempio # 1) o il tempo di compilazione (esempio # 2).

Il primo esempio richiede di passare una stringa per determinare il tipo di pizza, che può introdurre la possibilità di errori di runtime:

PizzaStore store = new PizzaStore();
Pizza pizza1 = store.orderPizza("chicago style"); // Seems right
Pizza pizza2 = store.orderPizza("blue jeans");    // Blatantly wrong, but compiles

Il secondo tipo di pizza probabilmente non sarà compreso dalla fabbrica di pizze (chi ha mai sentito parlare di una pizza "blue jeans"?) ea quel punto la fabbrica di pizze farà un'eccezione.

Il secondo esempio verifica la correttezza dei tipi di pizza al momento della compilazione perché stai utilizzando le classi e l'ereditarietà sia per i negozi di pizza che per gli stili di pizza.

    
risposta data 22.09.2017 - 17:28
fonte