Java - von am Dienstag, August 8, 2006 23:25 - 4 Kommentare

Factory Method Pattern in Java

Das Factory Method Pattern, die schreckliche deutsche Übersetzung lautet Fabrikmethode, stellt eine Schnittstelle für die Erzeugung eines Objekts bereit, überlässt aber die Entscheidung darüber, welche konkrete Klasse instanziiert werden soll, seinen Unterklassen. Das im folgenden aufgeführte Java-Beispiel beschreibt das Factory Method Pattern, wie es von der Gang of Four beschrieben wurde, anhand eines fiktiven Anwendungsfalles aus der Automobilbranche.

Zum leichteren Verständnis der Design Patterns möchte ich Ihnen den Bestseller Entwurfsmuster von Kopf bis Fuß nahelegen, welches die meiner Meinung nach verständlichste und beste Einführung in die Welt der Design Patterns bietet.

Kategorie

Das Factory Method Pattern wird zu den „Creational Patterns“ gezählt, da es Objekte erzeugt und zurückliefert.

Einsatzbereich

Das Factory Method Pattern kann eingesetzt werden, wenn:

  • Die aufrufende Klasse nicht weiß, welche konkrete Klasse instanziiert werden soll.
  • Die aufrufende Klasse nicht weiß, wie eine konkrete Klasse instanziiert werden muss.
  • Die aufrufende Klasse Informationen zur Erzeugung einer Klasse mitgibt, anhand dieser das Factory Method Pattern entscheidet, welche konkrete Klasse instanziiert wird.
  • Eine Klasse, die Verantwortung für die konkret zu erzeugende Klasse an ihre Unterklassen delegieren möchte.

UML-Klassendiagramm: Factory Method Pattern

Das UML-Klassendiagramm für das Factory Method Pattern sieht folgendermaßen aus:

UML-Klassendiagramm: Factory Method Pattern

Beispiel

In unserem stark vereinfachten Beispiel aus der Automobilbranche beginnen wir mit der abstrakten Klasse AbstrakterHersteller, die im UML-Klassenmodell die Klasse Creator repräsentiert. Sie hat einen Default-Constructor, also einen Constructor ohne Signatur, die als einzige Operation die Erzeugung von konkreten Fahrzeugen an abgeleitete Unterklassen delegiert, indem sie ihre abstrakte Methode erzeugeFahrzeuge() aufruft.

package de.theserverside.designpatterns.factorymethod;

import java.util.ArrayList;
import java.util.List;

/**
* Stellt im UML-Klassendiagramm "Creator" dar, von der konkrete
* Klassen abgeleitet werden, die auch instanziiert werden können.
*/
public abstract class AbstrakterHersteller {
protected List<abstraktesfahrzeug> fahrzeuge =
new ArrayList<abstraktesfahrzeug>();</abstraktesfahrzeug></abstraktesfahrzeug>

/**
* Delegiert die Instanziierung der konkreten Fahrzeuge an
* implementierende Unterklassen.
*
*/
public AbstrakterHersteller() {
this.erzeugeFahrzeuge();
}

public List<abstraktesfahrzeug> getFahrzeuge() {
return fahrzeuge;
}</abstraktesfahrzeug>

/**
* Muss von einer Methode überschrieben werden, die konkrete
* Fahrzeuge instanziiert. Dies ist das Herzstück des Factory
* Method Pattern
*
*/
protected abstract void erzeugeFahrzeuge();
}

Diese Klasse muss jetzt noch abgeleitet und die Implementierung der Methode erzeugeFahrzeuge() vervollständigt werden. Der Inhalt der Methode stellt die Verbindung namens „instantiates“ zwischen den Klassen ConcreteCreator und ConcreteProduct im UML-Klassendiagramm dar. Wir leiten AbstrakterHersteller im folgenden als Klasse BMW ab.

package de.theserverside.designpatterns.factorymethod;

/**
* Stellt im UML-Klassendiagramm "ConcreteCreator" dar, die die
* konkreten Klassen (ConcreteProduct) instanziiert.
*/
public class BMW extends AbstrakterHersteller {
/**
* Implementiert die abstrakte Methode aus der Oberklasse
* und erzeugt konkrete Fahrzeugobjekte
*/
protected void erzeugeFahrzeuge() {
fahrzeuge.add(new Z4(231));
}
}

Wir leiten AbstrakterHersteller ein zweites mal ab – dieses mal als Klasse Volkswagen.

package de.theserverside.designpatterns.factorymethod;

/**
* Stellt im UML-Klassendiagramm "ConcreteCreator" dar, die die
* konkreten Klassen (ConcreteProduct) instanziiert.
*/
public class Volkswagen extends AbstrakterHersteller {
/**
* Implementiert die abstrakte Methode aus der Oberklasse
* und erzeugt konkrete Fahrzeugobjekte
*/
protected void erzeugeFahrzeuge() {
fahrzeuge.add(new Passat(147));
fahrzeuge.add(new Touareg(331));
}
}

Wie man sieht, erzeugen die beiden Implementierungen von AbstrakterHersteller neue Objekte, in unserem Fall Fahrzeugmodelle der jeweiligen Hersteller. All diese Fahrzeuge wiederum sind abgeleitet von AbstraktesFahrzeug, was im UML-Klassendiagramm der Klasse Product entspricht. Es ist zu beachten, daß die genaue Ausprägung der Klasse Product nicht der Definition des Factory Method Pattern unterworfen ist. Die folgende Implementierung ist also spezifisch für unser Beispiel.

package de.theserverside.designpatterns.factorymethod;

/**
* Stellt im UML-Klassendiagramm "Product" dar, von der konkrete
* Klassen abgeleitet werden, die auch instanziiert werden können.
*/
public abstract class AbstraktesFahrzeug {
private String hersteller;
private String modell;
private int kw;

public String getHersteller() {
return hersteller;
}

public String getModell() {
return modell;
}
public int getKw() {
return kw;
}

public AbstraktesFahrzeug(String hersteller, String modell,
int kw) {
this.hersteller = hersteller;
this.modell = modell;
this.kw = kw;
}
}

Es folgt der letzte Bestandteil des Factory Method Pattern, das ConcreteProduct. In unserem Fall sind das Fahrzeuge der beiden Automobilhersteller.

Der BMW Z4…

package de.theserverside.designpatterns.factorymethod;

/**
* Stellt im UML-Klassendiagramm "ConcreteProduct" dar, die von
* der Factory Methode instanziiert wird.
*/
public class Z4 extends AbstraktesFahrzeug {
public Z4(int kw) {
super("BMW", "Z4", kw);
}
}

… ein Volkswagen Passat…

package de.theserverside.designpatterns.factorymethod;

/**
* Stellt im UML-Klassendiagramm "ConcreteProduct" dar, die von
* der Factory Methode instanziiert wird.
*/
public class Passat extends AbstraktesFahrzeug {
public Passat(int kw) {
super("Volkswagen", "Passat", kw);
}
}

… und der Volkswagen Touareg.

package de.theserverside.designpatterns.factorymethod;

/**
* Stellt im UML-Klassendiagramm "ConcreteProduct" dar, die von
* der Factory Methode instanziiert wird.
*/
public class Touareg extends AbstraktesFahrzeug {
public Touareg(int kw) {
super("Volkswagen", "Touareg", kw);
}
}

Die Implementierung dieses Beispiels dient nur der Anschaulichkeit. In einem realen Projekt würde man die Hierarchien anders abbilden und ggf. mit weniger Klassen auskommen. In unserem Beispiel müssten wir für jedes Fahrzeugmodell eine neue Klasse implementieren, was real natürlich nicht zielführend sein kann.

Um unsere Implementierung des Factory Method Pattern zu testen, dient folgende Klasse, die eine statische main(…)-Methode enthält, und damit als Anwendung aus der Konsole oder IDE gestartet werden kann.

package de.theserverside.designpatterns.factorymethod;

/**
* Testet die Implementation des Factory Method Pattern
*/
public class FactoryMethodMain {

public static void main(String[] args) {
/*
* Hersteller Volkswagen und BMW instanziieren
*/
AbstrakterHersteller vw = new Volkswagen();
AbstrakterHersteller bmw = new BMW();

/*
* Ausgabe der Fahrzeuge eines jeden Herstellers
*/
for (AbstraktesFahrzeug fahrzeug : vw.getFahrzeuge()) {
System.out.println(
fahrzeug.getHersteller() + " " +
fahrzeug.getModell() + ", " +
fahrzeug.getKw() + " KW");
}

for (AbstraktesFahrzeug fahrzeug : bmw.getFahrzeuge()) {
System.out.println(
fahrzeug.getHersteller() + " " +
fahrzeug.getModell() + ", " +
fahrzeug.getKw() + " KW");
}
}
}

Wenn Sie diese Klasse starten, müssten Sie als Ausgabe folgende Zeilen auf der out-Konsole sehen:

Volkswagen Passat, 147 KW
Volkswagen Touareg, 331 KW
BMW Z4, 231 KW

Damit ist die Einführung in das Factory Method Pattern abgeschlossen. Sollten Sie Anregungen oder Verbesserungsvorschläge haben – oder Fehler im Code sehen – hinterlassen Sie hier gerne einen Kommentar.

Sourcecode zum Artikel

Sourcecode: Factory Method Pattern

Weiterführende Literatur

Wer sich mit Design Patterns näher auseinandersetzen will, kommt um das Standardwerk der „Gang of Four“ (GoF) „Design Patterns“ nicht herum. Der Link führt zur englischen Ausgabe des Buches, da die deutsche Übersetzung sehr grausam ist…

Wenn Ihnen dieses Buch zu trocken ist und Sie leichter verdaubares Material suchen, sind die beiden folgenden Bücher zum Thema „Design Patterns“, bzw. „Design Patterns in Java“ auch sehr zu empfehlen.

Eine unterhaltsame und sehr leicht verständliche Einführung in die Thematik Design Patterns in Java finden Sie mit „Entwurfsmuster von Kopf bis Fuß„. Das gesamte Buch ist bebildert und anschaulich gestaltet, und die Konzepte werden didaktisch hervorragend erläutert. Die Codebeispiele sind in Java geschrieben und auf das Nötigste reduziert.

Das Buch „The Design Patterns Java Workbook“ arbeitet die Design Patterns der Reihe nach ab, aber nicht, ohne vorher die Grundlagen (Interfaces, Abstrakte Klassen etc.) zu erläutern. Jedes Kapitel enthält Aufgaben, die gelöst werden können und anhand derer das Erlernte sofort praktisch angewandt werden kann. Da bisher keine deutsche Übersetzung existiert (Stand: August 2006), müssen Sie noch mit der englischen Fassung vorlieb nehmen.



4 Kommentare

Sie können Kommentare zu diesem Artikel über den RSS 2.0-Feed nachverfolgen. Sie können einen Kommentar hinterlassen, oder einen Trackback von Ihrer eigenen Website setzen.

Tobias Heckmann
Jul 27, 2007 10:06

Eine Factory kann auch die Aufgabe haben, die Klassen, die sie produziert, verwaltet. Es sollte aus diesem Grund nicht von jedem Punkt im Programm aus möglich sein, eine bestimme Klasse zu initialisieren(ohne dies über die Factory zu tun). In C++ wird dies über das Attribut friend gemacht. Wie kann man so etwas in Java implementieren? Auf dies sollte in diesem Artikel eingegangen werden, da er sogar über Wikipedia verlinkt ist, und damit dem Anspruch auf Vollständigkeit gerecht werden sollte.

keywan
Mai 18, 2008 8:51

Auch die Frage fast ein Jahr alt ist will ich mich mal dran versuchen:
Friends gibt es in Java ja nicht. Soll eine Klasse nur von einer bestimmten, verwaltenden Fabrikklasse erzeugt werden können bietet sich in Java eine inner Klasse an. Bei meinem Beispiel möchte ich aber auf abstrakte Klassen verzichten, ich bevorzuge Interfaces, in dem oben angeführten UML wären Creater und Product also Interfaces.

public class ConcreteFactory implements Creator{
public Product factoryMethod(){
return new ConcreteProduct();
}

public static class ConcreteProduct implements Product{
private ConcreteProduct(){

}
}
}

Java Pattern – GeekLogy
Apr 30, 2012 11:04

[…] Java Pattern Web: Entwurfsmuster — Wikipedia Entwurfsmuster (englisch design patterns) sind bewährte Lösungsschablonen für wiederkehrende Entwurfsprobleme in Softwarearchitektur und Softwareentwicklung. de.wikipedia.org/wiki/Entwurfsmuster – besuchen Pattern (Java 2 Platform SE v1.4.2) public final class Pattern extends Object implements Serializable. A compiled representation of a regular expression. A regular expression, specified as a string, must first be … download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html – besuchen Factory Method Pattern in Java Detailliertes Tutorial zum Factory Method Pattern anhand eines Beispiels in Java. http://www.theserverside.de/factory-method-pattern-in-java – besuchen […]

link
Dez 25, 2023 5:03

link

theserverside.de – Factory Method Pattern in Java

Kommentieren

Weitere Empfehlungen:




-->

Java - Jul 19, 2011 20:30 - 0 Kommentare

Eine (wirklich gute) Einführung in Maven

Mehr Artikel der Kategorie Softwarearchitekturen


Datenbanken, Internet Technologien - Nov 19, 2009 9:24 - 0 Kommentare

Oracle WebServices im praktischen Einsatz

More In Datenbanken


Betriebssysteme - Jul 27, 2006 22:28 - 0 Kommentare

Angriff der Klone!

More In Betriebssysteme