Was ist eine "statische Fabrik" -Methode?
Was ist eine "statische Fabrik" -Methode?
Antworten:
Wir vermeiden den direkten Zugriff auf Datenbankverbindungen, da diese ressourcenintensiv sind. Daher verwenden wir eine statische Factory-Methode getDbConnection
, die eine Verbindung herstellt, wenn wir unter dem Grenzwert liegen. Andernfalls wird versucht, eine "Ersatz" -Verbindung bereitzustellen, die mit einer Ausnahme fehlschlägt, wenn keine vorhanden ist.
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);
//...
}
}
Das statische Factory-Methodenmuster ist eine Möglichkeit, die Objekterstellung zu kapseln. Ohne eine Factory-Methode würden Sie einfach den Konstruktor der Klasse direkt aufrufen : Foo x = new Foo()
. Mit diesem Muster würden Sie stattdessen die Factory-Methode aufrufen : Foo x = Foo.create()
. Die Konstruktoren sind als privat markiert, sodass sie nur innerhalb der Klasse aufgerufen werden können. Die Factory-Methode ist so markiert static
, dass sie aufgerufen werden kann, ohne zuvor ein Objekt zu haben.
Dieses Muster bietet einige Vorteile. Zum einen kann die Factory aus vielen Unterklassen (oder Implementierern einer Schnittstelle) auswählen und diese zurückgeben. Auf diese Weise kann der Aufrufer das gewünschte Verhalten über Parameter festlegen, ohne eine möglicherweise komplexe Klassenhierarchie kennen oder verstehen zu müssen.
Ein weiterer Vorteil besteht darin, wie Matthew und James hervorgehoben haben, den Zugriff auf eine begrenzte Ressource wie Verbindungen zu kontrollieren. Auf diese Weise können Pools wiederverwendbarer Objekte implementiert werden. Anstatt ein Objekt zu erstellen, zu verwenden und abzureißen, ist es möglicherweise sinnvoller, sie einmal zu erstellen und zu recyceln, wenn Konstruktion und Zerstörung teure Prozesse sind. Die Factory-Methode kann ein vorhandenes, nicht verwendetes instanziiertes Objekt zurückgeben, wenn es eines hat, oder eines erstellen, wenn die Objektanzahl unter einem unteren Schwellenwert liegt, oder eine Ausnahme auslösen oder zurückgeben, null
wenn sie über dem oberen Schwellenwert liegt.
Gemäß dem Artikel auf Wikipedia ermöglichen mehrere Factory-Methoden auch unterschiedliche Interpretationen ähnlicher Argumenttypen. Normalerweise hat der Konstruktor den gleichen Namen wie die Klasse, was bedeutet, dass Sie nur einen Konstruktor mit einer bestimmten Signatur haben können . Fabriken sind nicht so eingeschränkt, was bedeutet, dass Sie zwei verschiedene Methoden verwenden können, die dieselben Argumenttypen akzeptieren:
Coordinate c = Coordinate.createFromCartesian(double x, double y)
und
Coordinate c = Coordinate.createFromPolar(double distance, double angle)
Dies kann auch verwendet werden, um die Lesbarkeit zu verbessern, wie Rasmus feststellt.
HINWEIS! "Die statische Factory-Methode ist NICHT die gleiche wie das Factory-Methodenmuster " (c) Effektives Java, Joshua Bloch.
Factory-Methode: "Definieren Sie eine Schnittstelle zum Erstellen eines Objekts, aber lassen Sie die Klassen, die die Schnittstelle implementieren, entscheiden, welche Klasse instanziiert werden soll. Mit der Factory-Methode kann eine Klasse die Instanziierung auf Unterklassen verschieben" (c) GoF.
"Die statische Factory-Methode ist einfach eine statische Methode, die eine Instanz einer Klasse zurückgibt." (c) Effektives Java, Joshua Bloch. Normalerweise befindet sich diese Methode in einer bestimmten Klasse.
Der Unterschied:
Die Schlüsselidee der statischen Factory-Methode besteht darin, die Kontrolle über die Objekterstellung zu erlangen und diese vom Konstruktor an die statische Methode zu delegieren. Die Entscheidung für das zu erstellende Objekt erfolgt wie in Abstract Factory außerhalb der Methode (im allgemeinen Fall, jedoch nicht immer). Während die Schlüsselidee (!) Der Factory-Methode darin besteht, die Entscheidung zu delegieren, welche Klasseninstanz innerhalb der Factory-Methode erstellt werden soll. Beispielsweise ist die klassische Singleton-Implementierung ein Sonderfall der statischen Factory-Methode. Beispiel für häufig verwendete statische Factory-Methoden:
Die Lesbarkeit kann durch statische Factory-Methoden verbessert werden:
Vergleichen Sie
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.
zu
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);}
- haben Namen, im Gegensatz zu Konstruktoren, die Code verdeutlichen können.
- Sie müssen nicht bei jedem Aufruf ein neues Objekt erstellen. Objekte können zwischengespeichert und bei Bedarf wiederverwendet werden.
- kann einen Subtyp ihres Rückgabetyps zurückgeben - insbesondere kann ein Objekt zurückgegeben werden, dessen Implementierungsklasse dem Aufrufer unbekannt ist. Dies ist eine sehr wertvolle und weit verbreitete Funktion in vielen Frameworks, die Schnittstellen als Rückgabetyp für statische Factory-Methoden verwenden.
Alles läuft auf Wartbarkeit hinaus. Der beste Weg, dies auszudrücken, ist, wenn Sie das new
Schlüsselwort zum Erstellen eines Objekts verwenden, den Code, den Sie schreiben, an eine Implementierung zu koppeln.
Mit dem Factory-Muster können Sie trennen, wie Sie ein Objekt erstellen, und was Sie mit dem Objekt tun. Wenn Sie alle Ihre Objekte mit Konstruktoren erstellen, verdrahten Sie den Code, der das Objekt verwendet, im Wesentlichen fest mit dieser Implementierung. Der Code, der Ihr Objekt verwendet, ist von diesem Objekt "abhängig". Auf den ersten Blick scheint dies keine große Sache zu sein, aber wenn sich das Objekt ändert (denken Sie daran, die Signatur des Konstruktors zu ändern oder das Objekt zu unterordnen), müssen Sie zurückgehen und die Dinge überall neu verkabeln.
Heutzutage wurden Fabriken weitgehend zugunsten der Verwendung von Dependency Injection beiseite geschoben, da sie viel Kesselplattencode erfordern, der sich als etwas schwierig herausstellt, sich selbst zu warten. Die Abhängigkeitsinjektion entspricht im Wesentlichen Fabriken, ermöglicht jedoch die Angabe, wie Ihre Objekte deklarativ miteinander verbunden werden (durch Konfiguration oder Anmerkungen).
Wenn der Konstruktor einer Klasse privat ist, können Sie kein Objekt für eine Klasse von außerhalb erstellen.
class Test{
int x, y;
private Test(){
.......
.......
}
}
Wir können kein Objekt für die oben genannte Klasse von außerhalb erstellen. Sie können also nicht von außerhalb der Klasse auf x, y zugreifen. Was nützt diese Klasse dann?
Hier ist die Antwort: FACTORY- Methode.
Fügen Sie die folgende Methode in der obigen Klasse hinzu
public static Test getObject(){
return new Test();
}
Jetzt können Sie ein Objekt für diese Klasse von außerhalb erstellen. Wie der Weg ...
Test t = Test.getObject();
Daher wird eine statische Methode, die das Objekt der Klasse durch Ausführen ihres privaten Konstruktors zurückgibt, als FACTORY- Methode bezeichnet
.
Static Factory Method
gegenüber einem öffentlichen Konstruktor?
Ich dachte, ich werde diesem Beitrag etwas Licht auf das geben, was ich weiß. Wir haben diese Technik in unserem ausgiebig angewendet recent android project
. Stattdessen creating objects using new operator
können Sie auch static method
eine Klasse instanziieren. Codeauflistung:
//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();
}
}
Statische Methoden unterstützen die bedingte Objekterstellung : Jedes Mal, wenn Sie einen Konstruktor aufrufen, wird ein Objekt erstellt, aber das möchten Sie möglicherweise nicht. Angenommen, Sie möchten eine Bedingung nur dann überprüfen, wenn Sie ein neues Objekt erstellen möchten. Sie würden nicht jedes Mal eine neue Instanz von Vinoth erstellen, es sei denn, Ihre Bedingung ist erfüllt.
Ein weiteres Beispiel aus Effective Java .
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
Diese Methode übersetzt einen booleschen Grundwert in eine boolesche Objektreferenz. Die Boolean.valueOf(boolean)
Methode veranschaulicht uns, sie erstellt niemals ein Objekt. Die Möglichkeit static factory methods
, dasselbe Objekt aus wiederholten Objekten zurückzugeben, invocations
ermöglicht es den Klassen, jederzeit eine strikte Kontrolle darüber zu behalten, welche Instanzen vorhanden sind.
Static factory methods
ist, dass sie im Gegensatz constructors
dazu einen object
beliebigen subtype
ihrer Rückgabetypen zurückgeben können. Eine Anwendung dieser Flexibilität besteht darin, dass eine API Objekte zurückgeben kann, ohne ihre Klassen öffentlich zu machen. Das Ausblenden von Implementierungsklassen auf diese Weise führt zu einer sehr kompakten API.
Calendar.getInstance () ist ein gutes Beispiel für die oben, es auf dem Lokalisierungs - A erstellt abhängig BuddhistCalendar
, JapaneseImperialCalendar
oder standardmäßig ein Georgian
.
Ein anderes Beispiel, das ich denken könnte, ist Singleton pattern
, wo Sie Ihre Konstruktoren privat machen und eine eigene getInstance
Methode erstellen , bei der Sie sicherstellen, dass immer nur eine Instanz verfügbar ist.
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;
}
}
Eine Factory-Methode Eine Methode, die die Instanziierung eines Objekts abstrahiert. Im Allgemeinen sind Fabriken nützlich, wenn Sie wissen, dass Sie eine neue Instanz einer Klasse benötigen, die eine Schnittstelle implementiert, die implementierende Klasse jedoch nicht kennen.
Dies ist nützlich, wenn Sie mit Hierarchien verwandter Klassen arbeiten. Ein gutes Beispiel hierfür wäre ein GUI-Toolkit. Sie könnten einfach Aufrufe an die Konstruktoren für konkrete Implementierungen jedes Widgets fest codieren, aber wenn Sie jemals ein Toolkit gegen ein anderes austauschen wollten, hätten Sie viele Möglichkeiten zum Ändern. Durch die Verwendung einer Factory reduzieren Sie die Menge an Code, die Sie ändern müssten.
Einer der Vorteile von Static Factory besteht darin, dass diese API Objekte zurückgeben kann, ohne ihre Klassen öffentlich zu machen. Dies führte zu einer sehr kompakten API. In Java wird dies durch die Collections-Klasse erreicht, die etwa 32 Klassen verbirgt, wodurch die Collection-API sehr kompakt ist.
Eine statische Factory-Methode ist gut, wenn Sie sicherstellen möchten, dass nur eine einzige Instanz die zu verwendende konkrete Klasse zurückgibt.
In einer Datenbankverbindungsklasse möchten Sie möglicherweise, dass nur eine Klasse die Datenbankverbindung erstellt. Wenn Sie also von MySQL zu Oracle wechseln, können Sie die Logik in einer Klasse ändern, und der Rest der Anwendung wird dies tun Verwenden Sie die neue Verbindung.
Wenn Sie das Datenbank-Pooling implementieren möchten, erfolgt dies auch ohne Auswirkungen auf den Rest der Anwendung.
Es schützt den Rest der Anwendung vor Änderungen, die Sie möglicherweise an der Fabrik vornehmen. Dies ist der Zweck.
Der Grund dafür, dass es statisch ist, ist, wenn Sie eine begrenzte Ressource (Anzahl der Socket-Verbindungen oder Dateihandles) verfolgen möchten, kann diese Klasse verfolgen, wie viele ohnmächtig gemacht und zurückgegeben wurden, damit Sie die nicht erschöpfen begrenzte Ressource.
Einer der Vorteile der statischen Factory-Methoden mit privatem Konstruktor (die Objekterstellung muss für externe Klassen eingeschränkt worden sein, um sicherzustellen, dass Instanzen nicht extern erstellt werden) besteht darin, dass Sie instanzgesteuerte Klassen erstellen können . Und instanzgesteuerte Klassen garantieren, dass keine zwei gleich unterschiedlichen Instanzen existieren ( a.equals (b) genau dann, wenn a == b ), während Ihr Programm ausgeführt wird. Dies bedeutet, dass Sie die Gleichheit von Objekten mit dem Operator == anstelle der Methode equals überprüfen können , nach Effective Java.
Durch die Fähigkeit statischer Factory-Methoden, dasselbe Objekt aus wiederholten Aufrufen zurückzugeben, können Klassen jederzeit streng kontrollieren, welche Instanzen vorhanden sind. Klassen, die dies tun, sollen instanzgesteuert sein. Es gibt mehrere Gründe, instanzgesteuerte Klassen zu schreiben. Durch die Instanzsteuerung kann eine Klasse garantieren, dass es sich um einen Singleton (Punkt 3) oder einen nicht instabilen (Punkt 4) handelt. Außerdem kann eine unveränderliche Klasse (Punkt 15) garantieren, dass keine zwei gleichen Instanzen existieren: a.equals (b) genau dann, wenn a == b. Wenn eine Klasse diese Garantie übernimmt, können ihre Clients den Operator == anstelle der Methode equals (Object) verwenden, was zu einer verbesserten Leistung führen kann. Aufzählungstypen (Punkt 30) bieten diese Garantie.
Von Effective Java, Joshua Bloch (Punkt 1, Seite 6)
statisch
Ein Mitglied, das mit dem Schlüsselwort 'static' deklariert wurde.
Fabrikmethoden
Methoden, die neue Objekte erstellen und zurückgeben.
in Java
Die Programmiersprache ist relevant für die Bedeutung von "statisch", nicht jedoch für die Definition von "Fabrik".
Die Java-Implementierung enthält die Dienstprogrammklassen java.util.Arrays und java.util.Collections. Beide enthalten statische Factory-Methoden , Beispiele dafür und deren Verwendung:
Arrays.asList("1","2","3")
Collections.synchronizedList(..), Collections.emptyList(), Collections.unmodifiableList(...)
(Nur einige Beispiele konnten javadocs auf weitere Methodenbeispiele überprüfen. Https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html )
Auch die Klasse java.lang.String verfügt über solche statischen Factory-Methoden :
String.format(...), String.valueOf(..), String.copyValueOf(...)