Estratto differenze di configurazione di fabbrica

2

è una semplice fabbrica astratta. So che la fabbrica astratta è per selezionare una famiglia di prodotti. Ma la mia domanda è: possiamo ancora usare questo modello se ConcreteFactory1 ha bisogno di createProductC() ma ConcreteFactory2 no? E se non possiamo usare, come risolviamo questo problema?

    
posta Pareidolia 31.10.2017 - 23:14
fonte

3 risposte

2

can we still use this pattern if ConcreteFactory1 needs to createProductC() but ConcreteFactory2 don't?

Sì. Sì, puoi.

È molto più semplice capire questo modello quando stai guardando un codice client.

class Client {
    private AbstractFactory af;
    public client(AbstractFactory af) { this.af = af; }
    public toString() { 
        return String.format("%s %s %s", 
            af.createProductA(),  
            af.createProductB(),
            af.createProductC());
    }        
} 

Che potrebbe farti stampare

ProductA1 ProductB1 ProductC1

Oppure potrebbe farti stampare

ProductA2 ProductB2

Come tiriamo fuori quel po 'di magia? Pattern oggetto nullo! La mia implementazione preferita del modello di oggetto nullo è la stringa vuota: ""

Solo perché un oggetto esiste non significa che debba fare qualcosa. Quando segui il modello di oggetto nullo offri esattamente l'interfaccia prevista, ma chiamare i metodi fa un sacco di niente. Quindi, anche se il cliente chiedeva più di questi prodotti, solo i loro metodi toString() il modello di oggetto nullo non farebbe nulla quando richiesto.

Quanto bene funziona dipende in gran parte da come è scritto il cliente. Noterai che ci rimane ancora uno spazio finale. Ma evitiamo di dover testare quale fabbrica astratta abbiamo. Questo è fondamentale per rimanere orientati agli oggetti.

L'oggetto nullo può essere complesso come il client ha bisogno che sia. Lo schema di base è quello di renderlo sicuro, ma privo di senso, per eliminarlo. Nessuna eccezione generata. I metodi che restituiscono il vuoto semplicemente non fanno nulla. Nessun effetto collaterale I metodi che restituiscono una stringa restituiscono la stringa vuota. I metodi che restituiscono i numeri restituiscono 0 o 1 a seconda che il client si aggiunga o si moltiplica. I metodi che restituiscono le collezioni restituiscono raccolte vuote. Anche le monadi possono essere restituite se è quello che il cliente si aspetta, purché, alla fine, non facciano nulla, in silenzio.

    
risposta data 01.11.2017 - 02:27
fonte
2

can we still use this pattern if ConcreteFactory1 needs to createProductC() but ConcreteFactory2 don't?

Hai alcune opzioni di progettazione qui:

  1. Crea una fabbrica astratta separata per la creazione di C . Spesso è utile suddividere le interfacce factory astratte per prodotto a differenza di come il diagramma UML ha raggruppato CreateProductA e CreateProductB nella stessa interfaccia. Penso che questa sia la scelta giusta se il prodotto C non ha molto in comune con gli altri prodotti.
  2. Mantieni createProductC nello stesso factory astratto, ma cambia la sua firma per restituire ProductC o nulla (in Java questo sarebbe Option[ProductC] ). Ciò imporrà ai clienti di gestire il fatto che alcune fabbriche concrete non producono un prodotto C. In alternativa, lanciare un'eccezione controllata. Penso che questa sia la scelta giusta se il prodotto C è strettamente correlato ai prodotti A e B e la produzione di C è veramente facoltativa, ei clienti dovrebbero chiamarla solo se è disponibile in fabbrica.
risposta data 31.10.2017 - 23:29
fonte
0

Il tuo diagramma mostra solo 1 client, quindi avrà bisogno di createProductC o non lo farà, e se ne ha bisogno la fabbrica che non può fornire C non può essere usata.

Se hai più di un cliente, alcuni che hanno bisogno di C s e altri no, probabilmente vorrai più tipi di fabbrica

interface ABFactory {
    A createA();
    B createB();
}

interface ABCFactory {
    A createA();
    B createB();
    C createC();
}

E poi ogni fabbrica di cemento può implementare un sacco di interfacce.

 class Factory1 implements ABFactory, ABCFactory { ... }
 class Factory2 implements ABFactory { ... }

E ogni cliente può richiedere ciò che richiede

// can only use Factory1
class Client1 {
    private ABCFactory af;
    public client(ABCFactory af) { this.af = af; }
    public void doStuff() { 
        A a = af.createProductA();  
        B b = af.createProductB();
        C c = af.createProductC();
    }        
} 

// can use both Factory1 and Factory2
class Client2 {
    private ABFactory af;
    public client(ABFactory af) { this.af = af; }
    public void doStuff() { 
        A a = af.createProductA();  
        B b = af.createProductB();
    } 
} 
    
risposta data 01.11.2017 - 14:42
fonte

Leggi altre domande sui tag