Che cos'è un metodo "fabbrica statica"?
Che cos'è un metodo "fabbrica statica"?
Risposte:
Evitiamo di fornire accesso diretto alle connessioni al database perché richiedono molte risorse. Quindi usiamo un metodo factory statico getDbConnection
che crea una connessione se siamo al di sotto del limite. Altrimenti, tenta di fornire una connessione "di riserva", fallendo con un'eccezione se non ce ne sono.
public class DbConnection{
private static final int MAX_CONNS = 100;
private static int totalConnections = 0;
private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();
private DbConnection(){
// ...
totalConnections++;
}
public static DbConnection getDbConnection(){
if(totalConnections < MAX_CONNS){
return new DbConnection();
}else if(availableConnections.size() > 0){
DbConnection dbc = availableConnections.iterator().next();
availableConnections.remove(dbc);
return dbc;
}else {
throw new NoDbConnections();
}
}
public static void returnDbConnection(DbConnection dbc){
availableConnections.add(dbc);
//...
}
}
Il modello di metodo statico di fabbrica è un modo per incapsulare la creazione di oggetti. Senza un metodo factory, si sarebbe semplicemente chiamare la classe costruttore direttamente: Foo x = new Foo()
. Con questo modello, si sarebbe invece chiamare il metodo di fabbrica: Foo x = Foo.create()
. I costruttori sono contrassegnati come privati, quindi non possono essere chiamati se non dall'interno della classe e il metodo factory è contrassegnato in static
modo tale da poter essere chiamato senza prima avere un oggetto.
Ci sono alcuni vantaggi in questo modello. Uno è che la fabbrica può scegliere tra molte sottoclassi (o implementatori di un'interfaccia) e restituirla. In questo modo il chiamante può specificare il comportamento desiderato tramite parametri, senza dover conoscere o comprendere una gerarchia di classi potenzialmente complessa.
Un altro vantaggio è, come hanno sottolineato Matthew e James, controllare l'accesso a una risorsa limitata come le connessioni. Questo è un modo per implementare gruppi di oggetti riutilizzabili - invece di costruire, usare e demolire un oggetto, se la costruzione e la distruzione sono processi costosi potrebbe avere più senso costruirli una volta e riciclarli. Il metodo factory può restituire un oggetto istanziato non utilizzato se ne ha uno o costruirne uno se il conteggio degli oggetti è al di sotto di una soglia inferiore o generare un'eccezione o restituire null
se è al di sopra della soglia superiore.
Secondo l'articolo su Wikipedia, più metodi di fabbrica consentono anche interpretazioni diverse di tipi di argomenti simili. Normalmente il costruttore ha lo stesso nome della classe, il che significa che puoi avere un solo costruttore con una data firma . Le fabbriche non sono così vincolate, il che significa che puoi avere due diversi metodi che accettano gli stessi tipi di argomenti:
Coordinate c = Coordinate.createFromCartesian(double x, double y)
e
Coordinate c = Coordinate.createFromPolar(double distance, double angle)
Questo può anche essere usato per migliorare la leggibilità, come osserva Rasmus.
NOTA! "Il metodo statico di fabbrica NON è lo stesso del modello di Metodo di fabbrica " (c) Java efficace, Joshua Bloch.
Metodo Factory: "Definisci un'interfaccia per la creazione di un oggetto, ma lascia che le classi che implementano l'interfaccia decidano quale classe creare un'istanza. Il metodo Factory consente a una classe di rinviare l'istanza alle sottoclassi" (c) GoF.
"Il metodo factory statico è semplicemente un metodo statico che restituisce un'istanza di una classe." (c) Efficace Java, Joshua Bloch. Di solito questo metodo è all'interno di una particolare classe.
La differenza:
L'idea chiave del metodo statico di fabbrica è ottenere il controllo sulla creazione di oggetti e delegarlo dal metodo costruttore al metodo statico. La decisione dell'oggetto da creare è come in Abstract Factory presa fuori dal metodo (nel caso comune, ma non sempre). Mentre l'idea chiave (!) Del metodo Factory è quella di delegare la decisione su quale istanza della classe creare all'interno del metodo Factory. Ad esempio l'implementazione classica di Singleton è un caso speciale di metodo factory statico. Esempio di metodi di fabbrica statici comunemente usati:
La leggibilità può essere migliorata con metodi di fabbrica statici:
Confrontare
public class Foo{
public Foo(boolean withBar){
//...
}
}
//...
// What exactly does this mean?
Foo foo = new Foo(true);
// You have to lookup the documentation to be sure.
// Even if you remember that the boolean has something to do with a Bar
// you might not remember whether it specified withBar or withoutBar.
per
public class Foo{
public static Foo createWithBar(){
//...
}
public static Foo createWithoutBar(){
//...
}
}
// ...
// This is much easier to read!
Foo foo = Foo.createWithBar();
private Foo(boolean withBar){/*..*/}
public static Foo createWithBar(){return new Foo(true);}
public static Foo createWithoutBar(){return new Foo(false);}
- hanno nomi, a differenza dei costruttori, che possono chiarire il codice.
- non è necessario creare un nuovo oggetto ad ogni invocazione: gli oggetti possono essere memorizzati nella cache e riutilizzati, se necessario.
- possono restituire un sottotipo del loro tipo restituito - in particolare, possono restituire un oggetto la cui classe di implementazione è sconosciuta al chiamante. Questa è una funzionalità molto preziosa e ampiamente utilizzata in molti framework che utilizzano interfacce come tipo di ritorno di metodi statici di fabbrica.
Tutto si riduce alla manutenibilità. Il modo migliore per dirlo è ogni volta che usi la new
parola chiave per creare un oggetto, stai abbinando il codice che stai scrivendo a un'implementazione.
Il modello di fabbrica ti consente di separare il modo in cui crei un oggetto da ciò che fai con l'oggetto. Quando crei tutti i tuoi oggetti utilizzando i costruttori, stai essenzialmente cablando il codice che utilizza l'oggetto a tale implementazione. Il codice che utilizza il tuo oggetto è "dipendente da" quell'oggetto. Questo potrebbe non sembrare un grosso problema in superficie, ma quando l'oggetto cambia (pensa a cambiare la firma del costruttore o subclassare l'oggetto) devi tornare indietro e ricollegare le cose ovunque.
Oggi le fabbriche sono state ampiamente spazzate via a favore dell'utilizzo dell'iniezione di dipendenza perché richiedono un sacco di codice della piastra della caldaia che risulta essere un po 'difficile da mantenere. L'iniezione delle dipendenze è sostanzialmente equivalente alle fabbriche, ma ti consente di specificare come i tuoi oggetti vengono collegati in modo dichiarativo (attraverso la configurazione o le annotazioni).
Se il costruttore di una classe è privato, non è possibile creare un oggetto per la classe dall'esterno.
class Test{
int x, y;
private Test(){
.......
.......
}
}
Non è possibile creare un oggetto per la classe precedente dall'esterno. Quindi non puoi accedere a x, y dall'esterno della classe. Allora a che serve questa classe?
Ecco la risposta: metodo FABBRICA .
Aggiungi il metodo seguente nella classe sopra
public static Test getObject(){
return new Test();
}
Quindi ora puoi creare un oggetto per questa classe dall'esterno. Come il modo ...
Test t = Test.getObject();
Quindi, un metodo statico che restituisce l'oggetto della classe eseguendo il suo costruttore privato è chiamato metodo FACTORY
.
Static Factory Method
rispetto al costruttore pubblico?
Ho pensato di aggiungere un po 'di luce a questo post su quello che so. Abbiamo usato ampiamente questa tecnica nella nostra recent android project
. Invece di creating objects using new operator
te puoi anche usare static method
per creare un'istanza di una classe. Elenco dei codici:
//instantiating a class using constructor
Vinoth vin = new Vinoth();
//instantiating the class using static method
Class Vinoth{
private Vinoth(){
}
// factory method to instantiate the class
public static Vinoth getInstance(){
if(someCondition)
return new Vinoth();
}
}
I metodi statici supportano la creazione di oggetti condizionali : ogni volta che invochi un costruttore verrà creato un oggetto ma potresti non volerlo. supponiamo che tu voglia controllare alcune condizioni solo allora vuoi creare un nuovo oggetto. Non creeresti una nuova istanza di Vinoth ogni volta, a meno che la tua condizione non sia soddisfatta.
Un altro esempio tratto da Effective Java .
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
Questo metodo traduce un valore primitivo booleano in un riferimento a un oggetto booleano. Il Boolean.valueOf(boolean)
metodo ci illustra, non crea mai un oggetto. La possibilità di static factory methods
restituire lo stesso oggetto da ripetute invocations
consente alle classi di mantenere un controllo rigoroso su quali istanze esistono in qualsiasi momento.
Static factory methods
è che, a differenza constructors
, possono restituire uno object
qualsiasi subtype
del loro tipo di ritorno. Un'applicazione di questa flessibilità è che un'API può restituire oggetti senza rendere pubbliche le loro classi. Nascondere le classi di implementazione in questo modo porta a un'API molto compatta.
Calendar.getInstance () è un grande esempio per quanto sopra, si crea a seconda della localizzazione di una BuddhistCalendar
, JapaneseImperialCalendar
o da un'impostazione predefinita Georgian
.
Un altro esempio che potrei pensare è che Singleton pattern
, quando rendi privati i tuoi costruttori, crei un getInstance
metodo personale in cui ti assicuri che sia sempre disponibile solo un'istanza.
public class Singleton{
//initailzed during class loading
private static final Singleton INSTANCE = new Singleton();
//to prevent creating another instance of Singleton
private Singleton(){}
public static Singleton getSingleton(){
return INSTANCE;
}
}
Un metodo factory un metodo che estrae l'istanza di un oggetto. Generalmente le fabbriche sono utili quando sai che hai bisogno di una nuova istanza di una classe che implementa qualche interfaccia ma non conosci la classe di implementazione.
Ciò è utile quando si lavora con gerarchie di classi correlate, un buon esempio di questo potrebbe essere un toolkit GUI. Potresti semplicemente chiamare in codice i costruttori per implementazioni concrete di ciascun widget, ma se mai volessi scambiare un toolkit con un altro avresti un sacco di posti da cambiare. Usando una fabbrica riduci la quantità di codice che dovresti cambiare.
Uno dei vantaggi che deriva dalla fabbrica statica è che l'API può restituire oggetti senza rendere pubbliche le loro classi. Ciò ha portato ad API molto compatte. In java questo è ottenuto dalla classe Collections che nasconde circa 32 classi, il che rende l'API di raccolta molto compatta.
Un metodo factory statico è utile quando si desidera garantire che solo una singola istanza restituirà la classe concrete da utilizzare.
Ad esempio, in una classe di connessione al database, potresti voler avere una sola classe per creare la connessione al database, in modo che se decidi di passare da Mysql a Oracle, puoi semplicemente cambiare la logica in una classe e il resto dell'applicazione usa la nuova connessione.
Se si desidera implementare il pooling di database, ciò dovrebbe avvenire anche senza influire sul resto dell'applicazione.
Protegge il resto dell'applicazione dalle modifiche che è possibile apportare alla fabbrica, che è lo scopo.
Il motivo per cui è statico è se si desidera tenere traccia di alcune risorse limitate (numero di connessioni socket o handle di file), quindi questa classe può tenere traccia di quanti sono stati distribuiti e restituiti, quindi non esaurire il risorsa limitata.
Uno dei vantaggi dei metodi factory statici con costruttore privato (la creazione di oggetti deve essere stata limitata per le classi esterne per garantire che le istanze non vengano create esternamente) è che è possibile creare classi controllate dall'istanza. E le classi controllate dall'istanza garantiscono che non esistono due istanze distinte uguali ( a.equals (b) se e solo se a == b ) durante l'esecuzione del programma, ciò significa che è possibile verificare l'uguaglianza degli oggetti con l' operatore == invece del metodo uguale , secondo Effective java.
La capacità dei metodi statici di fabbrica di restituire lo stesso oggetto da invocazioni ripetute consente alle classi di mantenere un controllo rigoroso su quali istanze esistono in qualsiasi momento. Si dice che le classi che fanno questo siano controllate dall'istanza. Esistono diversi motivi per scrivere classi controllate dall'istanza. Il controllo dell'istanza consente a una classe di garantire che sia un singleton (elemento 3) o non affidabile (elemento 4). Inoltre, consente a una classe immutabile (elemento 15) di garantire che non esistono due istanze uguali: a.equals (b) se e solo se a == b. Se una classe offre questa garanzia, i suoi clienti possono utilizzare l'operatore == anziché il metodo equals (Object), il che può comportare un miglioramento delle prestazioni. I tipi Enum (Articolo 30) forniscono questa garanzia.
Da Effective Java, Joshua Bloch (Articolo 1, pagina 6)
statico
Un membro dichiarato con la parola chiave "statico".
metodi di fabbrica
Metodi che creano e restituiscono nuovi oggetti.
in Java
Il linguaggio di programmazione è rilevante per il significato di "statico" ma non per la definizione di "fabbrica".
L'implementazione Java contiene le classi di utilità java.util.Arrays e java.util.Collections contenenti entrambi metodi statici di fabbrica , esempi e modalità di utilizzo:
Arrays.asList("1","2","3")
Collections.synchronizedList(..), Collections.emptyList(), Collections.unmodifiableList(...)
(Solo alcuni esempi, potrebbe controllare javadocs per esempi di metodi mor https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html )
Anche la classe java.lang.String ha tali metodi factory statici :
String.format(...), String.valueOf(..), String.copyValueOf(...)