Comprendi le differenze nelle motivazioni:
Supponiamo che tu stia costruendo uno strumento in cui hai oggetti e un'implementazione concreta delle interrelazioni degli oggetti. Dato che prevedi variazioni negli oggetti, hai creato una direzione indiretta assegnando la responsabilità di creare varianti degli oggetti a un altro oggetto ( lo chiamiamo fabbrica astratta ). Questa astrazione trova un grande vantaggio poiché prevedi future estensioni che richiedono varianti di quegli oggetti.
Un'altra motivazione piuttosto intrigante in questa linea di pensiero è un caso in cui tutti gli oggetti di tutto il gruppo avranno una variante corrispondente. In base ad alcune condizioni, verrà utilizzata una delle varianti e in ogni caso tutti gli oggetti devono essere della stessa variante. Questo potrebbe essere un po 'contro intuitivo da capire, poiché spesso tendiamo a pensare che - purché le varianti di un oggetto seguano un contratto uniforme comune ( interfaccia in senso lato ), il codice di implementazione concreto non dovrebbe mai infrangersi. Il fatto interessante qui è che, non sempre questo è vero soprattutto quando il comportamento previsto non può essere modellato da un contratto di programmazione.
Un semplice ( prendendo in prestito l'idea da GoF ) è che qualsiasi applicazione GUI dice un monitor virtuale che emula l'aspetto di MS o Mac o del sistema operativo Fedora. Qui, ad esempio, quando tutti gli oggetti widget come finestra, pulsante, ecc. Hanno una variante MS ad eccezione di una barra di scorrimento derivata dalla variante MAC, lo scopo dello strumento fallisce male.
Questi casi di cui sopra costituiscono il bisogno fondamentale di Abstract Factory Pattern .
D'altra parte, immagina di scrivere un framework in modo che molte persone possano creare vari strumenti ( come quello negli esempi sopra ) usando il tuo framework. Dall'idea stessa di un framework, non è necessario, anche se non è possibile utilizzare oggetti concreti nella propria logica. Preferisci mettere alcuni contratti di alto livello tra vari oggetti e il modo in cui interagiscono. Mentre tu ( come sviluppatore di framework ) rimani a un livello molto astratto, ogni costruttore dello strumento è costretto a seguire i tuoi costrutti di framework. Tuttavia, loro ( i costruttori di strumenti ) hanno la libertà di decidere quale oggetto costruire e come interagiranno tutti gli oggetti che creano. A differenza del caso precedente ( di Abstract Factory Pattern ), tu ( come creatore di framework) in questo caso non è necessario lavorare con oggetti concreti; e piuttosto può rimanere a livello di contratto degli oggetti. Inoltre, a differenza della seconda parte delle motivazioni precedenti, tu o i costruttori di utensili non avete mai le situazioni di mescolare oggetti da varianti. Qui, mentre il codice del framework rimane a livello di contratto, ogni costruttore di strumenti è limitato ( dalla natura del caso stesso ) all'utilizzo dei propri oggetti. Le creazioni di oggetti in questo caso sono delegate a ciascun implementatore e i provider di framework forniscono solo metodi uniformi per la creazione e la restituzione di oggetti. Tali metodi sono inevitabili per lo sviluppatore del framework per procedere con il loro codice e ha un nome speciale chiamato metodo Factory ( Factory Method Pattern per il pattern sottostante ).
Alcune note:
- Se hai familiarità con il "metodo modello", allora vedresti che i metodi di fabbrica sono spesso invocati dai metodi modello nel caso di programmi appartenenti a qualsiasi forma di framework. Al contrario, i metodi modello di programmi applicativi sono spesso semplici implementazioni di algoritmi specifici e nulla di metodi di fabbrica.
- Inoltre, per la completezza dei pensieri, usando il framework ( menzionato sopra ), quando un costruttore di strumenti sta costruendo uno strumento, all'interno di ciascun metodo di fabbrica, invece di creare un oggetto concreto, può delegare ulteriormente la responsabilità a un abstract -oggetto di fabbrica, a condizione che il costruttore di strumenti preveda variazioni degli oggetti concreti per future estensioni.
Codice di esempio:
//Part of framework-code
BoardGame {
Board createBoard() //factory method. Default implementation can be provided as well
Piece createPiece() //factory method
startGame(){ //template method
Board borad = createBoard()
Piece piece = createPiece()
initState(board, piece)
}
}
//Part of Tool-builder code
Ludo inherits BoardGame {
Board createBoard(){ //overriding of factory method
//Option A: return new LudoBoard() //Lodu knows object creation
//Option B: return LudoFactory.createBoard() //Lodu asks AbstractFacory
}
….
}
//Part of Tool-builder code
Chess inherits BoardGame {
Board createBoard(){ //overriding of factory method
//return a Chess board
}
….
}