Modelli di progettazione: metodo Factory vs Factory vs Factory astratto


183

Stavo leggendo modelli di design da un sito Web

Lì ho letto di Factory, il metodo Factory e Abstract factory, ma sono così confusi, non sono chiaro sulla definizione. Secondo le definizioni

Factory: crea oggetti senza esporre la logica di istanza al client e fa riferimento all'oggetto appena creato tramite un'interfaccia comune. È una versione semplificata del metodo Factory

Metodo di fabbrica: definisce un'interfaccia per la creazione di oggetti, ma consente alle sottoclassi di decidere quale classe creare un'istanza e fa riferimento all'oggetto appena creato tramite un'interfaccia comune.

Fabbrica astratta: offre l'interfaccia per la creazione di una famiglia di oggetti correlati, senza specificare esplicitamente le loro classi.

Ho anche guardato gli altri thread dello stackover riguardo a Abstract Factory vs Factory Method ma i diagrammi UML tracciati lì peggiorano la mia comprensione.

Qualcuno può dirmelo

  1. In che modo questi tre schemi differiscono l'uno dall'altro?
  2. Quando usare quale?
  3. E anche se possibile, qualche esempio java relativo a questi schemi?

3
Mentre cercavo le risposte più o meno alla stessa domanda dell'OP, ho trovato questo articolo: Da nessuna fabbrica al metodo di fabbrica . Fornisce la comprensione seguendo l'evoluzione di un progetto di esempio (il metodo di fabbrica menzionato nel titolo è una delle fasi evolutive).
Nick Alexeev,

Risposte:


251

Tutti e tre i tipi di Factory fanno la stessa cosa: sono un "costruttore intelligente".

Diciamo che vuoi essere in grado di creare due tipi di frutta: mela e arancia.

Fabbrica

Factory è "riparato", in quanto hai una sola implementazione senza sottoclasse. In questo caso, avrai una classe come questa:

class FruitFactory {

  public Apple makeApple() {
    // Code for creating an Apple here.
  }

  public Orange makeOrange() {
    // Code for creating an orange here.
  }

}

Caso d'uso: costruire una Apple o una Orange è un po 'troppo complesso da gestire nel costruttore per nessuno dei due.

Metodo di fabbrica

Il metodo factory viene generalmente utilizzato quando si dispone di un'elaborazione generica in una classe, ma si desidera variare il tipo di frutta effettivamente utilizzato. Così:

abstract class FruitPicker {

  protected abstract Fruit makeFruit();

  public void pickFruit() {
    private final Fruit f = makeFruit(); // The fruit we will work on..
    <bla bla bla>
  }
}

... quindi puoi riutilizzare la funzionalità comune FruitPicker.pickFruit()implementando un metodo factory in sottoclassi:

class OrangePicker extends FruitPicker {

  @Override
  protected Fruit makeFruit() {
    return new Orange();
  }
}

Fabbrica astratta

La fabbrica astratta viene normalmente utilizzata per cose come l'iniezione / strategia di dipendenza, quando si desidera essere in grado di creare un'intera famiglia di oggetti che devono essere "dello stesso tipo" e avere alcune classi base comuni. Ecco un esempio vagamente legato alla frutta. Il caso d'uso qui è che vogliamo assicurarci di non utilizzare accidentalmente un OrangePicker su una Apple. Finché avremo i nostri frutti e raccoglitori dalla stessa fabbrica, si abbineranno.

interface PlantFactory {

  Plant makePlant();

  Picker makePicker(); 

}

public class AppleFactory implements PlantFactory {
  Plant makePlant() {
    return new Apple();
  }

  Picker makePicker() {
    return new ApplePicker();
  }
}

public class OrangeFactory implements PlantFactory {
  Plant makePlant() {
    return new Orange();
  }

  Picker makePicker() {
    return new OrangePicker();
  }
}

8
+1 Questa è la risposta più simile alla mia comprensione di questi schemi. Anche l'aggiunta di esempi di codice chiamante (client) sarebbe di aiuto? La domanda che mi preoccupa molto è: possiamo dire che Abstract Factory Pattern è solo Factory estesa con Factory Method Pattern (se questo è vero, sono chiaro su questo argomento)?
croraf

9
Questo è l'esempio che ho passato anni a cercare.
Taztingo,

Questa è una spiegazione fantastica! Grazie!
André Andrade,

@ AndréAndrade Come invocare il metodo Factory ? Un piccolo codice samle pls :) Ciò chiarirà il mio dubbio sul suo utilizzo
Arnab Dutta

25
  1. In che modo questi tre schemi differiscono l'uno dall'altro?

Factory: crea oggetti senza esporre la logica di istanza al client.

Metodo di fabbrica: definire un'interfaccia per la creazione di un oggetto, ma lasciare che le sottoclassi decidano quale classe creare un'istanza. Il metodo Factory consente a una classe di rinviare l'istanza alle sottoclassi

Fabbrica astratta: fornisce un'interfaccia per la creazione di famiglie di oggetti correlati o dipendenti senza specificare le loro classi concrete.

Il modello AbstractFactory utilizza la composizione per delegare la responsabilità della creazione di oggetti in un'altra classe mentre il modello di progettazione del metodo Factory utilizza l'ereditarietà e si basa sulla classe o sottoclasse derivata per creare l'oggetto

  1. Quando usare quale?

Factory: il cliente ha solo bisogno di una classe e non si preoccupa di quale implementazione concreta sta ottenendo.

Metodo di fabbrica: il client non sa quali classi concrete sarà necessario creare in fase di esecuzione, ma vuole solo ottenere una classe che farà il lavoro.

AbstactFactory: quando il sistema deve creare più famiglie di prodotti o si desidera fornire una libreria di prodotti senza esporre i dettagli di implementazione.

Le classi Abstract Factory sono spesso implementate con il metodo Factory. I metodi di fabbrica sono generalmente chiamati all'interno dei metodi modello.

  1. E anche se possibile, qualche esempio java relativo a questi schemi?

Factory and FactoryMethod

Intent:

Definire un'interfaccia per la creazione di un oggetto, ma lasciare che le sottoclassi decidano quale classe creare un'istanza. Il metodo Factory consente a una classe di rinviare l'istanza alle sottoclassi.

Diagramma UML :

inserisci qui la descrizione dell'immagine

Prodotto: definisce un'interfaccia degli oggetti creati dal metodo Factory.

ConcreteProduct: implementa l'interfaccia del prodotto

Creatore: dichiara il metodo Factory

ConcreateCreator: implementa il metodo Factory per restituire un'istanza di ConcreteProduct

Dichiarazione del problema: crea una Factory of Games usando Factory Methods, che definisce l'interfaccia di gioco.

Snippet di codice:

Modello di fabbrica. Quando utilizzare i metodi di fabbrica?

Confronto con altri schemi di creazione:

  1. Il design inizia con il metodo Factory (meno complicato, più personalizzabile, le sottoclassi proliferano) e si evolve verso Abstract Factory, Prototype o Builder (più flessibile, più complesso) man mano che il progettista scopre dove è necessaria maggiore flessibilità

  2. Le classi Factory astratte sono spesso implementate con i metodi Factory , ma possono anche essere implementate usando Prototype

Riferimenti per ulteriori letture: modelli di progettazione per la creazione di sorgenti


Per il metodo Factory, non dovrebbe essere definita una superclasse?
Tony Lin,

21

Factory - Separa la classe Factory per creare oggetti complessi.

Es: classe FruitFactory per creare l'oggetto di Fruit

class FruitFactory{

public static Fruit getFruit(){...}

}

Metodo di fabbrica - Invece di un'intera classe separata per factory, basta aggiungere un metodo in quella classe stessa come factory.

Ex:

Calendar.getInstance() (Java's Calendar)

Metodo astratto di fabbrica - Fabbrica di fabbrica

Es .: Diciamo che vogliamo costruire una fabbrica per parti di computer. Quindi ci sono diversi tipi di computer come laptop, desktop, server.

Quindi per ogni tipo di compter abbiamo bisogno di fabbrica. Quindi creiamo una fabbrica di alto livello di fabbriche come di seguito

ComputerTypeAbstractFactory.getComputerPartFactory(String computerType) ---> This will return PartFactory which can be one of these ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Ora questi 3 sono di nuovo fabbriche. (Avrai a che fare con PartFactory stesso, ma sotto il cofano, ci sarà un'implementazione separata basata su ciò che hai fornito in fabbrica astratta)

  Interface-> PartFactory. getComputerPart(String s), 
Implementations -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory.

Usage:
new ComputerTypeAbstractFactory().getFactory(“Laptop”).getComputerPart(“RAM”)

EDIT: modificato per fornire interfacce esatte per Abstract Factory secondo le obiezioni nei commenti.


1
L'idea alla base ComputerFactorysarebbe quella di avere un'interfaccia di creazione comune ( getScreen(); getKeyboard(); getDiskdrive(); ...), non un'interfaccia per tipo di computer come suggerisci. Puoi annusare un problema di progettazione se usi la stessa parola due volte nella stessa affermazione: Laptop Factory.get Laptop Part ().
xtofl,

No no no, non andare esattamente sul codice stesso. Era solo un'anologia per la comprensione. Se vuoi l'esempio esatto con le interfacce, eccolo qui. Oggetti: Interfaccia -> ComputerPart, Implementazione -> RAM, HDD, Processor Factory: Interface-> PartFactory. getComputerPart (String s), Implements -> ServerPartFactory, LaptopPartFactory, DesktopPartFactory. Fabbrica astratta: ComputerType.getPartFactory ("String s") Utilizzo: nuovo ComputerType (). GetFactory ("Laptop"). GetComputerPart ("RAM")
Ravi K

2
Ho una risposta aggiornata per occuparmi della tua preoccupazione. La fabbrica in realtà astratta non è altro che una fabbrica di fabbrica. Ho dato un esempio precedente solo per riferimento (Supponendo che i lettori si prenderanno cura delle interfacce durante l'implementazione effettiva). Ancora grazie per averlo avvisato. È sempre bene migliorare. :)
Ravi K,

No abstract Factorynon è una fabbrica di fabbrica ... È una abstract classo una interfacecapacità di creare oggetti che saranno implementati / estesi con diverse fabbriche di cemento. Vedi la risposta accettata per i dettagli del codice. E rimuovi o modifica la risposta di conseguenza.
Julien__

Mi piace la spiegazione del metodo di fabbrica, che è abbastanza conciso da svelare perché è così chiamato. In questo modello, la fabbrica è il metodo, NON la classe che generalmente non è un'utilità di aiuto che raggruppa i metodi di istanza ma significativa da sola. Altre risposte più elaborate sfortunatamente sfuggirono a questo punto.
wlnirvana,

11

Ogni modello di progettazione prospera per garantire che il codice scritto e funzionante non venga toccato. Sappiamo tutti che una volta toccato il codice di lavoro, ci sono difetti nei flussi di lavoro esistenti e sono necessari molti più test per garantire che non abbiamo rotto nulla.

Un modello di fabbrica crea oggetti in base a criteri di input, garantendo così che non è necessario scrivere codice come se questo quindi crea questo oggetto kinda altrimenti questo oggetto kinda. Un buon esempio di questo è un sito web di viaggi. Un sito Web di viaggi può fornire solo viaggi (volo, treno, autobus) o / e fornire hotel o / e fornire pacchetti di attrazioni turistiche. Ora, quando un utente seleziona successivamente, il sito Web deve decidere quali oggetti deve creare. Dovrebbe solo creare l'oggetto di viaggio o hotel.

Ora, se prevedi di aggiungere un altro sito Web al tuo portafoglio e ritieni che venga utilizzato lo stesso core, ad esempio un sito Web di carsharing, che ora cerca i taxi ed effettua pagamenti online, puoi utilizzare una fabbrica astratta nel tuo core. In questo modo puoi semplicemente scattare in un'altra fabbrica di cabine e carpools.

Entrambe le fabbriche non hanno nulla a che fare l'una con l'altra, quindi è un buon design per tenerle nelle diverse fabbriche.

Spero che questo sia chiaro ora. Studia di nuovo il sito Web tenendo presente questo esempio, speriamo che possa essere d'aiuto. E spero davvero di aver rappresentato correttamente gli schemi :).


3

Per questa risposta, mi riferisco al libro "Gang of Four".

Non ci sono nessun né definizioni di "Factory", né "Simple Factory" "fabbrica virtuale" nel libro. Di solito quando le persone parlano del modello "Factory" possono parlare di qualcosa che crea un particolare oggetto di una classe (ma non il modello "builder"); che può o non può fare riferimento alla "Factory Method" o "modelli di Abstract Factory". Chiunque può implementare "Factory" come non vuole perché non è un termine formale (tenere presente che alcune persone / società \ comunità possono avere il proprio vocabolario).

Il libro contiene solo le definizioni di "Fabbrica astratta" e "Metodo di fabbrica".

Ecco le definizioni del libro e una breve spiegazione del perché entrambi possono essere così confusi. Ometto esempi di codice perché puoi trovarli in altre risposte:

Metodo di fabbrica (GOF) : definisce un'interfaccia per la creazione di un oggetto, ma consente alle sottoclassi di decidere quale classe creare un'istanza. Il metodo Factory consente a una classe di rinviare l'istanza alle sottoclassi.

Abstract Factory (GOF) : fornisce un'interfaccia per la creazione di famiglie di oggetti correlati o dipendenti senza specificare le loro classi concrete.

Fonte di confusione : spesso, si può chiamare una classe utilizzata nel modello "Metodo di fabbrica" ​​come "Fabbrica". Questa classe è astratta per definizione. Ecco perché è facile chiamare questa classe "Fabbrica astratta". Ma è solo il nome della classe; non dovresti confonderlo con il modello "Fabbrica astratta" (nome classe! = nome modello). Il modello "Fabbrica astratta" è diverso: non utilizza una classe astratta; definisce un'interfaccia (non necessariamente un'interfaccia del linguaggio di programmazione) per la creazione di parti di un oggetto più grande o di oggetti correlati tra loro o che devono essere creati in un modo particolare.


2
AbstractProductA, A1 and A2 both implementing the AbstractProductA
AbstractProductB, B1 and B2 both implementing the AbstractProductB

interface Factory {
    AbstractProductA getProductA(); //Factory Method - generate A1/A2
}

Utilizzando il metodo Factory, l'utente può creare A1 o A2 di AbstractProductA.

interface AbstractFactory {
    AbstractProductA getProductA(); //Factory Method
    AbstractProductB getProductB(); //Factory Method
}

Ma Abstract Factory ha più di 1 metodo factory (es: 2 metodi factory), usando quei metodi factory creerà l'insieme di oggetti / oggetti correlati. Utilizzando Abstract Factory, l'utente può creare oggetti A1, B1 di AbstractProductA, AbstractProductB


0

Nessuno ha citato il libro originale Design Patterns: Elements of Reusable Object-Oriented Software , che fornisce la risposta nei primi due paragrafi della sezione "Discussion of Creational Patterns" (sottolineatura mia):

Esistono due modi comuni per parametrizzare un sistema in base alle classi di oggetti che crea. Un modo è sottoclassare la classe che crea gli oggetti; ciò corrisponde all'utilizzo del modello Metodo di fabbrica (107). Lo svantaggio principale di questo approccio è che può richiedere una nuova sottoclasse solo per cambiare la classe del prodotto. Tali cambiamenti possono andare in cascata. Ad esempio, quando il creatore del prodotto stesso viene creato con un metodo di fabbrica, è necessario sovrascrivere anche il suo creatore.

L'altro modo di parametrizzare un sistema si basa maggiormente sulla composizione degli oggetti : definire un oggetto responsabile della conoscenza della classe degli oggetti del prodotto e renderlo un parametro del sistema. Questo è un aspetto chiave dei modelli Abstract Factory (87), Builder (97) e Prototype (117). Tutti e tre implicano la creazione di un nuovo "oggetto di fabbrica" ​​la cui responsabilità è quella di creare oggetti di prodotto. Abstract Factory ha l'oggetto factory che produce oggetti di diverse classi. Il costruttore ha l'oggetto factory che costruisce un prodotto complesso in modo incrementale usando un protocollo altrettanto complesso. Prototype ha l'oggetto factory che costruisce un prodotto copiando un oggetto prototipo. In questo caso, l'oggetto di fabbrica e il prototipo sono lo stesso oggetto, poiché il prototipo è responsabile della restituzione del prodotto.

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.