Perché abbiamo bisogno del modello astratto di design di fabbrica?


124

La maggior parte della definizione dice:

Una fabbrica astratta fornisce un'interfaccia per creare famiglie di oggetti correlati senza specificare le loro classi concrete

Qual è l'uso del modello astratto di fabbrica in quanto possiamo realizzare il compito creando l'oggetto della stessa classe concreta. Perché abbiamo un metodo factory che crea oggetti di classe Concrete?

Forniscimi qualche esempio di vita reale in cui devo implementare il modello abstractFactory?

Risposte:


219

6
Tutti questi esempi descrivono il modello di metodo di fabbrica, poiché tutti restituiscono una singola interfaccia di prodotto. Nessuno di questi è un modello di fabbrica astratto, perché nessuno di essi produce una famiglia di interfacce di prodotto correlate.
jaco0646,

32
Nell'interesse di una completa divulgazione, l'autore di questa risposta avrebbe dovuto chiarire che è anche l'autore di ciascuna delle risposte collegate; quindi questo elenco NON è un campione rappresentativo della comunità SO.
jaco0646,

1
@ jaco0646 IIRC, il modello Metodo di fabbrica è una specializzazione del modello Metodo modello , che si basa sull'eredità. Potrei sbagliarmi, però, poiché attualmente sto viaggiando e non ho il mio libro GoF con me. Cosa intendi con "nessuno di loro produce una famiglia di interfacce di prodotto correlate"?
Mark Seemann,

1
L'indizio più semplice che indica che una fabbrica non è conforme al modello astratto di fabbrica è di contare i prodotti astratti che la fabbrica produce (ho usato il termine "interfacce di prodotto" al posto di "prodotti astratti" per evitare un uso eccessivo della parola "astratto") . Una fabbrica che produce un singolo prodotto astratto non può essere una Fabbrica astratta, perché per definizione, la Fabbrica astratta produce una famiglia di prodotti correlati . È fondamentale notare che questa famiglia non si riferisce a implementazioni diverse di un'unica interfaccia, ma piuttosto a prodotti con interfacce diverse e correlate.
jaco0646,

1
Ecco un esempio oodesign.com/abstract-factory-pattern.html . Questo è ciò per cui è stato originariamente creato il modello astratto di fabbrica.
user2802557,

23

Un esempio di vita reale per l'uso del modello Abstract Factory è fornire l'accesso ai dati a due diverse origini dati. Supponiamo che l'applicazione supporti diversi archivi di dati. (ad es. un database SQL e un file XML). Esistono due diverse interfacce di accesso ai dati, ad esempio un IReadableStoree la IWritableStoredefinizione dei metodi comuni previsti dalla propria applicazione indipendentemente dal tipo di origine dati utilizzata.

Il tipo di origine dati da utilizzare non deve modificare il modo in cui il codice client recupera le sue classi di accesso ai dati. Il vostro AbstractDataAccessFactorysa che tipo di origine dati è configurata e fornisce un concreto fabbrica per il codice del client, ad esempio SqlDataAccessFactoryo XmlDataAccessFactory. Queste fabbriche di cemento in grado di creare il calcestruzzo implementazioni, ad esempio, SqlReadableStoree SqlWriteableStore.

Il DbProviderFactory NET Framework è un esempio di questo modello.


18
Questa risposta potrebbe descrivere accuratamente il modello Metodo di fabbrica, o Modello di fabbrica statico, ma non il modello di Fabbrica astratta.
jaco0646,

5

Se ti capisco bene, la domanda è: perché abbiamo sia il metodo Factory sia i modelli factory astratti. È necessaria una fabbrica astratta quando diverse classi polimorfiche hanno una diversa procedura di istanziazione. E vuoi che un modulo crei istanze e le usi, senza conoscere alcun dettaglio sull'inizializzazione degli oggetti. Ad esempio: si desidera creare oggetti Java facendo alcuni calcoli. Ma alcuni di essi fanno parte dell'applicazione, mentre altri bytecode dovrebbero essere letti dal DB. D'altra parte - perché abbiamo bisogno del metodo di fabbrica? D'accordo, quella fabbrica astratta la sovrappone. Ma in alcuni casi - scrivere codice è molto meno, avere meno classi e interfacce rende il sistema più semplice da comprendere.


3

Qual è l'uso del modello astratto di fabbrica in quanto possiamo realizzare il compito creando l'oggetto della stessa classe concreta. Perché abbiamo un metodo factory che crea oggetti di classe Concrete?

In assenza di Abstract Factory , il Cliente deve conoscere i dettagli di classi concrete. Questo accoppiamento stretto è stato rimosso con la Fabbrica astratta .

Ora il metodo di fabbrica espone un contratto che il cliente deve usare. È possibile aggiungere più prodotti alla propria fabbrica aggiungendo nuovi prodotti, che implementano l'interfaccia esposta dal Metodo di fabbrica.

Fare riferimento a queste domande SE correlate per una migliore comprensione:

Qual è la differenza di base tra i modelli Factory e Abstract Factory?

Intent:

Fornire un'interfaccia per la creazione di famiglie di oggetti correlati o dipendenti senza specificare le loro classi concrete.

Puoi capire Intento, Struttura, Lista di controllo e Regole empiriche del modello di Fabbrica astratta da questo articolo di creazione di fonti .

Elenco di controllo:

  1. Decidi se i servizi di indipendenza e creazione della piattaforma sono l'attuale fonte di dolore.
  2. Mappare una matrice di piattaforme rispetto ai prodotti .
  3. Definire un'interfaccia di fabbrica che consiste in un metodo di fabbrica per prodotto.
  4. Definire una classe derivata dalla fabbrica per ciascuna piattaforma che incapsuli tutti i riferimenti al nuovo operatore.
  5. Il client deve ritirare tutti i riferimenti a nuovi e utilizzare i metodi factory per creare gli oggetti prodotto .

2

Le fabbriche astratte sono ottime per supportare più piattaforme mantenendo unificata la tua base di codice. Supponiamo di avere un grande programma Qt o GTK + o .NET / Mono che si desidera eseguire su Windows, Linux e OSX. Ma hai una funzione che è implementata in modo diverso su ogni piattaforma (forse tramite l'API kernel32 o una funzione POSIX).

public abstract class Feature
{
    public abstract int PlatformSpecificValue { get; }

    public static Feature PlatformFeature
    {
        get
        {
            string platform;
            // do platform detection here
            if (platform == "Win32")
                return new Win32Feature();
            if (platform == "POSIX")
                return new POSIXFeature();
        }
    }

    // platform overrides omitted
}

Con questa fabbrica astratta, la tua interfaccia utente non ha bisogno di sapere nulla sulla piattaforma attuale.

Feature feature = Feature.PlatformFeature;
Console.WriteLine(feature.PlatformSpecificValue);

1
Non capisco, in che modo è diverso dal solo usare i metodi di fabbrica per restituire un tipo astratto in modo che il client non conosca i dettagli dell'implementazione?
kiwicomb123,

1

Se si osservano i motivi di progettazione, quasi tutti possono essere resi ridondanti. Ma quale modello significa un approccio comunemente usato per una soluzione a un tipo simile di problemi. Un modello di progettazione fornisce un approccio o una soluzione a livello di progettazione a una serie di problemi di progettazione simili. L'utilizzo del modello di progettazione consente di risolvere il problema e quindi di consegnarlo più rapidamente.



1

Trovo il modello di Fabbrica astratta sopravvalutato.

Prima di tutto, non accade che spesso che si dispone di un set di interrelati tipi che si desidera creare un'istanza.

In secondo luogo, il livello di riferimento indiretto (astrazione) fornito dalle interfacce è normalmente sufficiente quando si lavora con l'iniezione di dipendenza.

L'esempio tipico di WindowsGui vs MacGui vs ... dove avresti un WindowsButton, MacButton, WindowsScrollBar, MacScrollbar, ecc. È spesso più facile da implementare definendo pulsanti concreti , barre di scorrimento, ecc. Usando il modello Visitatore e / o Interprete per fornire comportamento reale.


c'è uno scopo specifico per questo. con l'iniezione delle dipendenze non si desidera localizzare i servizi più in basso dalla radice composita. invece usi una fabbrica astratta iniettata.
Adam Tuliper - MSFT,

2
bene ... l'uso del localizzatore di servizi con DI è un anti-patteren. Una Fabbrica astratta è la soluzione universale quando dobbiamo creare DEPENDENZE dai valori di runtime.
TheMentor,

1

Penso che ci sia un posto per un modello di fabbrica astratto piuttosto che un semplice modello di fabbrica in luoghi in cui le tue istanze sono molto complicate, troppo complicate e brutte per una singola fabbrica e troppo complicate per la comprensione dell'interfaccia utente.

Diciamo che questo è un marchio TYPE_A non una singola classe .. diciamo che esiste una famiglia di 100 tipi di classi simili di Tipo A e devi istanziarne un oggetto. Immagina che siano necessarie informazioni sofisticate per ottenere l'oggetto corretto da una marca di molti tipi simili di oggetti e in questa entità oggetto devi sapere esattamente quali parametri mettere a punto e come metterli a punto.

Nella fabbrica speciale per questo marchio li faremo differenziare e ottenere l'oggetto esatto da istanziare e anche come istanziarlo. lo sapremo in base all'input proveniente dalla rete (diciamo di che colore è disponibile nel negozio online) e da altre applicazioni e servizi in esecuzione in background (parametri che l'IU non ne è a conoscenza).

E forse domani avremo un'altra famiglia di diciamo type_B e type_C per istanziare. Quindi l'interfaccia utente avrà "if else" per sapere se l'utente desidera un "tipo_A", "tipo_B" o "tipo_C" - ma le classi delle fabbriche decideranno esattamente quale classe del tipo (dalla famiglia) costruire, e come ottimizzarlo: quali valori impostare sui suoi parametri o inviare al suo appaltatore. Tutto ciò, in base a molti parametri di cui l'interfaccia utente non è a conoscenza. Tutto questo sarà troppo per una singola classe di fabbrica.


0

Per rispondere direttamente alla tua domanda, puoi probabilmente scappare senza utilizzare un tale modello di progettazione.

Tuttavia, tieni presente che la maggior parte dei progetti nel mondo reale si evolve e desideri fornire un qualche tipo di estensibilità per rendere il tuo progetto a prova di futuro.

Dalla mia esperienza, il più delle volte, viene implementata una Fabbrica e man mano che il progetto cresce viene trasformato in modelli di progettazione più complessi come una Fabbrica astratta.


0

Si tratta di dipendenze. Se non ti interessa l'accoppiamento stretto e le dipendenze, non hai bisogno di una fabbrica astratta. Ma sarà importante non appena si scrive un'applicazione che richiede manutenzione.


0

Supponi di creare a.jar e che qualcun altro usi il tuo jar e desideri utilizzare un nuovo oggetto concreto nel tuo codice. Se non stai usando la factory astratta, allora deve modificare il tuo codice o sovrascriverlo. Ma se stai usando la fabbrica astratta, allora può fornire una fabbrica e passare al tuo codice e tutto va bene.

Versione raffinata: considera lo scenario qui sotto : Qualcun altro ha scritto un framework. Il framework utilizza una fabbrica astratta e alcune fabbriche concrete per creare molti oggetti in fase di esecuzione. In questo modo è possibile registrare facilmente la propria fabbrica nel framework esistente e creare i propri oggetti. Il framework è chiuso alle modifiche ed è ancora facile da estendere a causa del modello astratto di fabbrica.


0

Questo modello è particolarmente utile quando il client non sa esattamente quale tipo creare. Ad esempio, supponiamo che uno Showroom che vende esclusivamente telefoni cellulari ottenga una query per gli smartphone realizzati da Samsung. Qui non conosciamo il tipo esatto di oggetto da creare (supponendo che tutte le informazioni per un telefono siano racchiuse nella forma di un oggetto concreto). Ma sappiamo che stiamo cercando smartphone fabbricati da Samsung. Queste informazioni possono essere effettivamente utilizzate se il nostro progetto ha un'implementazione astratta in fabbrica.

Comprensione e implementazione del modello astratto di fabbrica in C #


0

L'esempio di vita reale è fornito nello spazio dei nomi System.Data.Common che ha classi di base astratte che includono DbConnection, DbCommand e DbDataAdapter e sono condivise dai provider di dati .NET Framework, come System.Data.SqlClient e System.Data.OracleClient che consentire a uno sviluppatore di scrivere un codice di accesso ai dati generico che non dipende da uno specifico fornitore di dati.

La classe DbProviderFactories fornisce metodi statici per la creazione di un'istanza DbProviderFactory. L'istanza quindi restituisce un oggetto fortemente tipizzato corretto in base alle informazioni del provider e alla stringa di connessione fornita in fase di esecuzione.

Esempio:

 DataTable allProvidersTable = DbProviderFactories.GetFactoryClasses();

inserisci qui la descrizione dell'immagine

        /* Getting SqlClient family members */
        DbProviderFactory dbProviderFactory = DbProviderFactories.GetFactory("System.Data.SqlClient");
        DbCommand dbCommand = dbProviderFactory.CreateCommand();
        DbConnection dbConnection = dbProviderFactory.CreateConnection();
        DbDataAdapter dbDataAdapter = dbProviderFactory.CreateDataAdapter();

        SqlClientFactory sqlClientFactory = (SqlClientFactory)dbProviderFactory;
        SqlConnection sqlConnection = (SqlConnection)dbConnection;
        SqlCommand sqlCommand = (SqlCommand) dbCommand;
        SqlDataAdapter sqlDataAdapter = (SqlDataAdapter) dbDataAdapter;

        /* Getting OracleClient family members*/
        dbProviderFactory = DbProviderFactories.GetFactory("System.Data.OracleClient");
        dbCommand = dbProviderFactory.CreateCommand();
        dbConnection = dbProviderFactory.CreateConnection();
        dbDataAdapter = dbProviderFactory.CreateDataAdapter();

        OracleClientFactory oracleClientFactory = (OracleClientFactory)dbProviderFactory;
        OracleConnection oracleConnection = (OracleConnection)dbConnection;
        OracleCommand oracleCommand = (OracleCommand)dbCommand;
        OracleDataAdapter oracleDataAdapter = (OracleDataAdapter)dbDataAdapter;

Esempio-2 inserisci qui la descrizione dell'immagine

Architettura della soluzione di codice inserisci qui la descrizione dell'immagine

Le istanze concrete della fabbrica sono fornite usando il metodo Factory statico come di seguito

public  class FurnitureProviderFactory
{
    public static IFurnitureFactory GetFactory(string furnitureType)
    {
        if (furnitureType == "Wood")
        {
            return new WoodenFurnitureFactory();
        }
        if (furnitureType == "Plastic")
        {
            return new PlasticFurnitureFactory();
        }
        throw new Exception("Undefined Furniture");
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.