Abstract Factory si adatta perfettamente.
C'è un principio di base che afferma che una classe dovrebbe fare bene una cosa. Il tuo problema qui è che stai cercando di fare molte classi fare molte cose.
Non è necessario attenersi a una fabbrica astratta. Puoi (e dovresti avere) più:
AbstractProductAFactory
definisce l'interfaccia per la produzione di ProdottoA. Le tue implementazioni concrete (ConcreteProductAFactory1, ConcreteProductAFactory2) lo estenderebbero.
AbstractProductBFactory
definisce l'interfaccia per la produzione di ProdottoB. Le tue implementazioni concrete ( ConcreteProductBFactory1
, ConcreteProductBFactory2
) lo estenderebbero.
Se hai bisogno di un ProductC, crea un nuovo AbstractProductCFactory
. Non c'è bisogno di cambiare nessuna delle tue altre fabbriche in questo modo.
Aggiorna
Idealmente, ProductA dovrebbe rappresentare una classe di prodotto, ovvero tutti i prodotti che condividono un'interfaccia che si chiama ProductA. Nei commenti suggerisco che si tratti di una pizza:
interface AbstractPizzaFactory {
public Pizza buildPizza(List<Topping> toppings);
}
class ThinCrustPizzaFactory implements AbstractPizzaFactory {
public Pizza buildPizza(List<Topping> toppings){
...
}
}
class DeepDishPizzaFactory implements AbstractPizzaFactory {
public Pizza buildPizza(List<Topping> toppings){
...
}
}
E così via. L'aggiunta di PanPizzaFactory non influisce su nessuna delle altre classi: è solo una nuova implementazione concreta di PizzaFactory. Se hai prodotti che non sono pizze - sandwich, ad esempio, è lì che crei un'altra fabbrica astratta (ad esempio AbstractSandwichFactory
).
Il vero punto è che non vorrai avere una fabbrica astratta che costruisca due tipi di prodotti molto diversi con due diversi metodi di "costruzione". Raggruppale nel modo più logico possibile in modo che condividano un'interfaccia e quindi creare una fabbrica astratta che definisca in che modo le fabbriche concrete dovrebbero implementare le implementazioni di tale interfaccia.