|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
[Programmazione OO\Java] Chiarimenti su pattern creazionali Factory
Ciao,
stò studiando i pattern ed avrei qualche dubbio che spero mi possiate chiarire. Attualmente stò vedendo i pattern creazionali ed in particolar modo i Factory. Faccio riferimento a questa slide: http://www.informatica.uniroma2.it/u...tern%20GOF.pdf Praticamente da quello che ho capito una factory è una speciale classe introdotta arbitrariamente (pure fabrication dei pattern GRASP) che ha la responsabilità di creare i miei oggetti e scelgo di introdurre questa nuova classe per fare creazioni complesse in oggetti coesi (per garantire high coesion e low coupling di fatto). Vabbè ci sono vari tipi di Factory...per quanto riguarda la abstract factory tutto ok... Mi stò impicciando non poco a capire cosa faccia invece la Lazy Factory...che praticamente dovrebbe usare la combinazione di un factory method e del memorizzare l'istanza creata su una mappa solo la prima volta e di poter riprendere la stessa istanza la volta successiva che si richede la stessa con certi parametri...fà questo esempio Codice:
import java.util.*; public class Fruit { /* Crea una HashMap comune a tutte le istanze della classe Fruit */ private static Map types = new HashMap(); private string type; private Fruit(String type){ // COSTRUTTORE this.type = type; // Assegna il parametro locale type types.put(type, this); // Che fà esattamente ?!?! } /* Metodo statico comune a tutta la classe che dato un parametro type ritorna un * oggetto di tipo Fruit */ public static Fruit getFruit(String type){ Fruit f; if(types.containskey(type)){ // Se nella hashmap c'è il valore type f = (fruit) types.get(type); // Mette quell'oggetto in f } else{ f = new Fruit(type); // Altrimenti lo crea con quel valore } return f; // Ritorna il riferimento ad f } } A che mi serve esattamente un pattern del genere? quand'è che si usa all'atto pratico? Alla riga types.put(type, this); fà l'inserimento nella hashmpa, praticamente gli stà dicendo di inserire lo specifico oggetto (this) relativo a quel valore type? Sapete darmi qualche info sulle hashmap? mai viste da praticamente nessun'altra parte :-/ Grazie |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
L' inizializzazione lazy, tenta di ritardare la costruzione di un oggetto nel momento effettivo in cui occorre. Oltre a cio, nel tuo esempio, viene creata una mappa di singletono, in modo da ridurre l' utilizzo di memoria.
|
![]() |
![]() |
![]() |
#3 | ||
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Risposta parziale (i design pattern non sono il mio forte)
Quote:
Quando un certo 'type' viene richiesto tramite 'getFruit', viene restituita l'istanza creata e memorizzata nella mappa. Se quell'istanza nella mappa non c'è, la si crea. Quindi per ogni 'type' richiesto esiste solo una istanza che viene condivisa. Tenendo in conto questo fatto, e visto il contesto (parlavi di factory patterns) mi viene in mente che questo sistema possa servire per istanziare una sola volta una specifica factory concreta. Quote:
Fa parte del "Collections Framework" distribuito con il JDK standard. Una Map è l'interfaccia ad un oggetto che mappa chiavi con valori. Nel codice che hai postato non vengono usati i Generics, quindi non viene dichiarto il tipo esplicito che la mappa usa per la chiave (Key) e per il valore (Value) ma esaminando la chiamata a 'put' si vede che il primo argomento (key) è di tipo String e il secondo argomento (value) di tipo Fruit. L'interfaccia Map fornisce tre "viste" che permettono di esaminare il contenuto di una Map come: - un set delle chiavi contenute; - una collezione dei valori contenuti; - un set di coppie chiave-valore. L'ordine della Map è definito dall'ordine con cui gli iteratori delle tre viste della mappa iterano gli elementi. Alcune implementazioni (come TreeMap) grantiscono un certo ordine, altre (come appunto HashMap) no. Si raccomanda fortemente l'uso di oggetti immutabili come chiavi di una Map (String per l'appunto è immutabile). Comunque qui trovi un trail se vuoi approfondire: Java Collection Framework
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
||
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
Quote:
Già che ci sono chiedo un'altra cosa per togliermi un altro dubbio...cosa intendi esattamente con: "mi viene in mente che questo sistema possa servire per istanziare una sola volta una specifica factory concreta." ? Cioè...dici che potrebbe essere usato come factory di factory concrete? o ho capito male? TNX |
|
![]() |
![]() |
![]() |
#5 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Il metodo factory è quello statico getFruit che è l' unico in grado di istanziare oggetti di tipo Fruit, classe nella quale sono presenti solo costruttori privati.
Poi ovviamente puoi utilizzare lo stesso sistema anche per creare factory di altri altri factory, ma non è il caso in esempio. |
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Una cosa che mi viene in mente, forse un'osservazione banale. Se usi questo sistema per creare istanze che poi vengono condivise, è meglio (anche se non è obbligatorio) che gli oggetti creati siano immutabili. Nel caso specifico poi (Fruit), devono proprio esserlo, per evitare che chi ottiene la data reference Fruit con la chiave "mela" mi faccia, ad esempio, un setType("pera"), con tutte le conseguenze del caso...
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
![]() |
![]() |
![]() |
#7 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
E' necessario che gli oggetti siano immutabili: in maniera assoluta non è necessario, ma dipende dal caso particolare. E' fondamentale che però siano thread safe, cosa che il codice in esempio non è in quanto il "factory method" non implementa strumenti di sincronizzazione.
Cose fondamentali, oltre al thread-safe sono: -non implementare clonable (o costruttori di copia profonda) -non implementare serializable -rendere il reference persistente Le prime 2 impediscono di ottenere subdolamente istanze non univoche, il terzo di impedire al garbace collector di deallocare l' oggetto o la classe stessa. |
![]() |
![]() |
![]() |
#8 | |
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Nel senso: nell'esempio proposto non mi pare ci sia bisogno di fare alcunchè, in merito, giusto? Non appena viene richiesta una qualsiasi istanza di Fruit del tipo 'type' viene creata l'istanza e messa nella mappa (che è static, e private). Da quel momento in poi l'istanza può solo essere referenziata da N reference al di fuori di Fruit, e anche se fossero zero resterebbe sempre referenziata dalla mappa, no?
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
|
![]() |
![]() |
![]() |
#9 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
ma nessuno ti garantisce che il GC, sussitendo le condizioni, deallochi la classe con le sue componenti statiche.
In tal caso basta far referenziare la mappa da un runnable con il metodo run in wait(). |
![]() |
![]() |
![]() |
#10 | ||
Senior Member
Iscritto dal: Oct 2007
Città: Padova
Messaggi: 4131
|
Quote:
Quali sarebbero, in due parole, queste condizioni? Quote:
![]()
__________________
As long as you are basically literate in programming, you should be able to express any logical relationship you understand. If you don’t understand a logical relationship, you can use the attempt to program it as a means to learn about it. (Chris Crawford) |
||
![]() |
![]() |
![]() |
#11 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Le classi e le interfacce vengono scaricate qualora il proprio classloader decida in tal senso oppure sia esso stesso soggetto al GC. Di norma le classi caricate dal bootstrap class loader non non soggette ad unload.
|
![]() |
![]() |
![]() |
#12 |
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
Ragazzi,
ora vi faccio una domanda che non c'entra molto...ma...io ora stò studiando queste slide del corso...ok...le capisco ma mai mi verrebbero in mente tutte le cose che state tirando fuori voi due ![]() ![]() ![]() E' una questione di esperienza sul campo che si acquisice con tempo e pratica o dite che c'è proprio da studiare anche altre cose? |
![]() |
![]() |
![]() |
#13 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
che corso di laurea frequenti?
|
![]() |
![]() |
![]() |
#14 |
Senior Member
Iscritto dal: Feb 2009
Messaggi: 700
|
|
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Per quanto riguarda i pattern è importante il modo in cui è stato tenuto il corso di ingnegneria del software. Se è stato svolto in maniera adeguata dovresti avere la mente già predisposta a pensare, metodicamente, il software in maniera non monolita.
Per quanto riguarda le specifiche dei singoli linguaggi, bisogna andare a leggere la documentazione ufficiale disponibile. |
![]() |
![]() |
![]() |
#16 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
L'HashSet in questione verrà garbage-collected solo in caso la sua reference venga posta esplicitamente a null o la classe che lo contiene venga rimossa dal classloader manualmente o automaticamente nel caso di uscita dall'applicazione. Non vedo il motivo per referenziare la mappa all'interno di un runnable in wait. comunque riguardo a quel codice io lo scriverei così dato che imho sarebbe più chiaro: Codice:
import java.util.*; public interface IFruit { public String myMethod(); } public class Apple implements IFruit { public Apple() { } public String myMethod { } } public class Orange implements IFruit { public Orange() { } public String myMethod { } } public class FruitFactory { private static Map<String, IFruit> fruits = new HashMap<String, IFruit>(); public static IFruit getFruit(Class clazz) { String type = clazz.getName(); return fruits.containsKey(type) ? fruits.get(type) : clazz.newInstance(); } } public class MainApp() { public MainApp() { Apple apple = FruitFactory.getFruit(Apple.class); Orange orange = FruitFactory.getFruit(Orange.class); } }
__________________
![]() Ultima modifica di ^TiGeRShArK^ : 15-05-2010 alle 10:35. |
|
![]() |
![]() |
![]() |
#17 | |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
Quote:
|
|
![]() |
![]() |
![]() |
#18 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
Quindi, a meno della rimozione fatta esplicitamente sul classloader che avevo menzionato in precedenza mi sfugge perchè usando un custom class loader sia necessario utilizzare un runnable per mantenere attiva la reference della map....
__________________
![]() |
|
![]() |
![]() |
![]() |
#19 |
Senior Member
Iscritto dal: Mar 2007
Messaggi: 7863
|
java.lang.ClassLoader è una classe astratta. La jvm ne possiede una implementazione di default, utilizzata qualora non venga esplicitamente utilizzato un classLoader customizzato.
Nessuno vieta di costruirsene uno a proprio piacimento. Il GC, si premura solo di non scaricare le classi referenziate dal loader nativo, su tutto il resto può applicare i proprio algoritmi di pulizia. |
![]() |
![]() |
![]() |
#20 | |
Senior Member
Iscritto dal: Jul 2002
Città: Reggio Calabria -> London
Messaggi: 12112
|
Quote:
Nel caso di classi statiche esse verrano rimosse solo quando viene rimosso il corrispettivo classloader.
__________________
![]() |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 22:40.