Diskussion:Fabrikmethode
alte Disku
statische FabrMethode
zu 2) Der Begriff Fabrikmethode wird in der Praxis auch oft für eine statische Methode verwendet, die ein neues Objekt erzeugt. In diesem Fall ist keine Verwendung von Unterklassen bzw. Polymorphismus vorgesehen.
eigener Artikel
es wäre gut, wenn die statische Fabrik (als Programmierideom und nicht als Entwurfsmuster) einen eigenen Artikel bekäme und entsprechend verlink wird
UML-Diagramm
- Seit der änderung am 22. Okt. 2006 scheint vor dem UML Diagramm ohne ersichtlichen grund ein "1)" zu stehen, macht das irgendwie sinn? --213.164.89.130 10:04, 12. Okt. 2007 (CEST)
- Ich sehe nicht, wo da eine 1) steht. Ich sehe aber an mehreren Stellen (1) und (2), was ich gerne entfernen würde, weil ich nicht weiß, worauf es sich bezieht. Ach so, auf Gliederungspunkt 1 und 2. Das ist sehr verwirrend. Ich würde das gerne explizit machen. --Wikiplex 16:16, 26. Aug. 2009 (CEST)
- Guck mal aufs Datum. Das ist wohl längst überholt... -- Der Hâkawâti ✉ 18:29, 26. Aug. 2009 (CEST)
Verständnisfrage zum UML-Diagramm
Wozu ist diese eineOperation() von Erzeuger gut? Wer benutzt sie?
- Das ist eine totale Fehlbezeichnung. Die eineOperation() sollte liefereNeuesObjekt() heißen, denn sie ist diejenige, die tatsächlich angestossen wird, um ein neues konkretes Objekt zu bauen. Sie ruft selbst die Fabrikmethode auf (die in der konkreten Klasse entsprechend implementiert ist). Wenn mir jemand einen Tipp gibt, mit welchem (freien) Malprogramm man am schnellsten diese Bildchen malt (Umbrello?), dann ändere ich das. --Wikiplex 16:20, 26. Aug. 2009 (CEST)
- Zusatz: Das steht eineOperation(), weil im GoF-Buch im Bildchen für die abstrakte Struktur die Bezeichnung AnOperation() steht. :-) --Wikiplex 19:11, 26. Aug. 2009 (CEST)
- eineOperation() ist schon richtig. liefereNeuesObjekt() würde ja bedeuten, dass die Methode das Obejkt zurückliefert. Das tut sie aber - im Allgemeinen - nicht. Sie verwendet nur die Fabrikmethode um das erzeugte Objekt intern irgendwie zu nutzen. Man weiß über die Mthode nichts, außer, dass die die Fabrikmethode nutzt, deshalb ist die allgemeien Bezeichnung "eineMethode" richtig. -- Der Hâkawâti ✉ 20:55, 27. Aug. 2009 (CEST)
Sinn fehlt
Warum werden Factories überhaupt noch genutzt?
- Die Frage impliziert die Aussage, dass sie früher einen Sinn hatten, jetzt aber nicht mehr. Das ist falsch. Schau dir mal das C++-Beispiel im Artikel an. Der Sinn des Musters ist die Verwendung in einem Framework, in dem Objekte kreiert werden müssen, deren Typ der Erschaffer des Frameworks zu seinem Kodierzeitpunkt noch nicht kennen kann. (Er kann ja nicht alle möglichen Verwendungen erahnen. Im Beispiel: Er weiß nicht, welche Arten von Restaurants und Mahlzeiten jemals ersonnen werden werden.) --Wikiplex 10:43, 27. Aug. 2009 (CEST)
Bildbeschreibung fehlt bei [[Bild:Fabrikmethode.png]]
Der Artikel enthält ein Bild, dem eine Bildbeschreibung fehlt, überprüfe bitte, ob es sinnvoll ist, diese zu ergänzen. Gerade für blinde Benutzer ist diese Information sehr wichtig. Wenn du dich auskennst, dann statte bitte das Bild mit einer aussagekräftigen Bildbeschreibung aus. Suche dazu nach der Textstelle [[Bild:Fabrikmethode.png]] und ergänze sie.
- Wenn du eine fehlende Bildbeschreibung ergänzen willst, kannst du im Zuge der Bearbeitung folgende Punkte prüfen:
- Namensraum Datei: Bilder sollte im Namensraum Datei liegen. Bitte ändere die alten Bezeichnungen
Bild:
undImage:
inDatei:
. - Skalierung: Außerhalb von Infoboxen sollten keine festen Bildbreiten (zum Beispiel 100px) verwendet werden. Für den Fließtext im Artikelnamensraum gibt es Thumbnails in Verbindung mit der automatischen Skalierung. Um ein Bild/eine Grafik in besonderen Fällen dennoch größer oder kleiner darzustellen, kann der „upright“-Parameter verwendet werden. Damit erfolgt eine prozentuale Skalierung, die sich an den Benutzereinstellungen orientiert. --SpBot 22:21, 1. Mär. 2009 (CET)
- Namensraum Datei: Bilder sollte im Namensraum Datei liegen. Bitte ändere die alten Bezeichnungen
Ist erledigt. Kann man diesen Punkt jetzt aus der Diskussion löschen? --Wikiplex 11:07, 27. Aug. 2009 (CEST)
Beispiele
Ich habe mal ein Beispiel in C++ eingefügt. Ich hoffe, es ist instruktiv und gefällt. Es ist ein Beispiel für die Original-Interpretation des Musters aus dem GoF-Buch. Habe mir viel Mühe gegeben. Was allerdings unter dem Punkt "Beispiele" davor steht, finde ich verwirrend bis unverständlich. Das sind ja teilweise nicht mal vollständige deutsche Sätze. Hat jemand was dagegen, wenn ich das komplett überarbeite? --Wikiplex 19:15, 26. Aug. 2009 (CEST)
- Schönes Beispiel. Allerdings hab ich da so ein paar Kritikpunkte. Ich lass jetzt mal so n paar sprachliche Dinge(z.B. "gebackt"==>"gebacken") und spreche erstmal das Inhaltliche an. Den sprachlichen Kleinkram kann man später immer noch verbessern.
- " // Hier wird das konkrete Produkt erzeugt, aber das ist *nicht* die
// Factory-Methode. Diese Methode wird von der Factory-Methode benutzt. virtual void zubereiteMahlzeit() = 0;" ==> Doch genau das ist die Factory-Methode.
- " void liefereMahlzeit() { // Das ist die Factory-Methode" ==> Demgegenüber ist das hier "eineOperation" bzw. anOperation(). Hier wird die Factory-Methode *genutzt*.
Zu dem Abschnitt: Ja, den könnte man wirklich mal überarbeiten. --Der Hâkawâti ✉ 21:23, 27. Aug. 2009 (CEST)
- Hallo Hakawati! Du hast doppelt Recht (recht?). Lustigerweise habe ich über "gebackt/gebacken" schon nachgedacht und mich für das erste entschieden, weil es in meinem Heimatdialekt dieses Partizip gibt in der Verwendung "Ich habe nach der Sauftour eine Pizza gebackt". (Deutung überlasse ich deiner Intuition.) Und ja, klar ist zubereiteMahlzeit() die Factory-Methode. Ich war durch das GoF-Buch verwirrt, wo es im Eingangsbeispiel "CreateDocument()" und "NewDocument()" gibt (was didaktisch nicht besonders gelungen ist). Ich werde Beispiel und Einleitung entsprechend ändern. Grüße! --Wikiplex 22:41, 27. Aug. 2009 (CEST)
- So, jetzt hab ich nur noch ein paar kleinere Kritikpunkte:
- zubereiteMahlzeit() ==> bereiteMahlzeitZu()
- Die Parameter sind etwas merkwürdig. Die Pizzeria kennt nur eine Sorte Pizzas. Klar ist das nur ein fiktives Beispiel, aber, wenn der Parameter keinen Mehrwert hat, kann man ihn ja weglassen und dadurch die Verständlichkeit erhöhen.
- Zutat für eine Rostwurst (im Übrigen in meinen Ohren ein ungewöhnlicher Begriff, aber der Duden scheint ihn zu kennen...) ist eine Weißwurst? In Bayern würde man dich dafür vermutlich Teeren und Federn. *g* Eine Weißwurst wird nicht gebraten oder gerillt, sondern gekocht. Das, was man in anderen Teilen Deutschlands - u.a. auch da, wo ich her komme - manchmal unter "Weißwurst" versteht, ist eigentlich gar keine. Zudem stört mich hier der Begriff "Zutat". Vorschlag; Wie wärs mit "Beilage"(Pommes, Brot, Brötchen, ...)
- Ist es in C++ (eine?) Konvention, Felder mit einem Unterstrich beginnen zu lassen? Sry, ich schreibe nicht so viel C++...
- --Der Hâkawâti ✉ 22:02, 28. Aug. 2009 (CEST)
- So, jetzt hab ich nur noch ein paar kleinere Kritikpunkte:
- Hier meine Antworten auf deine vier Kritikpunkte:
- Klar ist "zubereite Mahlzeit" grammatisch falsch. Aber ich möchte mich beim OOD bei der Vergabe von Methodennenamen strikt an die syntaktische Reihenfolge <Verb im Imperativ> [<Akkusativ-Objekt> [<Dativ-Objekt> [<Adverbiale Umstandsangabe> ]]] halten. Das ist im Deutschen halt u.U. etwas holprig, weil die Präpositionen von Komposita in manchen Fällen ans Ende des Satzes gezogen werden müssen ("bereite X für Y in Z zu"). Ich will das Äquivalent haben zu "make meal".
- Ich wollte einen Parameter haben um zu verdeutlichen, dass der Erzeuger tatsächlich etwas tut (tun kann), außer nur das Objekt anzulegen. Vielleicht wäre es instruktiver, wenn er mit set-Methoden die Zutaten einzeln dazutut, aber dann wird das Beispiel komplizierter (und man wird dann evtl. durch die in Pizza enthaltene Containerklasse vom Wesentlichen abgelenkt). Aber das ist wahrscheinlich auch nicht der Punkt. nimmBestellungAuf() sollte die Bestellung abfragen und der Erzeuger dementsprechend dann den Konstruktor geeignet parametrisiert aufrufen. Hmmm, ich sollte nach meiner obigen Forderung "aufnehmeBestellung" verwenden, aber das ist wirklich zu grauenhaft. :-)
- Rostwurst, Weißwurst, Beilage: Hast völlig recht. Werde das ändern. Vielleicht fliegt die Beilage als Parameter nach dieser Diskussion eh aus dem Beispiel raus.
- Es ist eine gängige Kodier-Konvention in C++, private Member mit einem Unterstrich beginnen zu lassen.
- --Wikiplex 12:07, 29. Aug. 2009 (CEST)
- Was ist Sinn und Zweck von solchen Konventionen? Lesbarkeit. Ziel ist es, dass man das gut lesen kann. Wenn man noch englische Bezeichner nähme (das würde ich prinzipiell bevorzugen, aber da wir hier in der deutschen Wikipedia sind, will ich nix gegen deutsche Bezeichner sagen), kann man guten Code prinzipiell fast wie einen englischen Prosa-Text lesen. Bei deutchen Bezeichnern wird dann eben Denglisch, aber auch hier sollte IMHO das Augenmerk auf der Lesbarkeit liegen und nicht auf den Konventionen, die die Lesbarkeit erreichen sollen.
daToni.bereiteMahlzeitZu()
ist eben einfach lesbar. Fast so wie "Toni, bereit' mal die Mahlzeit zu!". Jetzt zum Vergleich:daToni.zubereiteMahlzeit()
. Da kannst du schwer einen geraden deutschen Satz draus machen. Dass sichaufnehmeBestellung()
bescheuert anhört, hast du ja selbst schon gemerkt. Was aber ist der Unterschied zuzubereiteMahlzeit()
? Konventionen sind gut und schön, nur sollte man nicht Konventionen um der Konventionen willen einhalten, sondern, weil sie einen sinnvollen Zweck haben. Zumal man hier die Konvention nur zuBezeichner = ersterTeilImperativ Objekt [zweiterTeilImperativ]
erweitern muss... - Wenn man nur bei der Wurst den Parameter Beilage hat und bei der Pizza keinen, kann man zusätzlich noch (implizit) zeigen, dass die Signaturen nicht übereinstimmen müssen.
- Was ist Sinn und Zweck von solchen Konventionen? Lesbarkeit. Ziel ist es, dass man das gut lesen kann. Wenn man noch englische Bezeichner nähme (das würde ich prinzipiell bevorzugen, aber da wir hier in der deutschen Wikipedia sind, will ich nix gegen deutsche Bezeichner sagen), kann man guten Code prinzipiell fast wie einen englischen Prosa-Text lesen. Bei deutchen Bezeichnern wird dann eben Denglisch, aber auch hier sollte IMHO das Augenmerk auf der Lesbarkeit liegen und nicht auf den Konventionen, die die Lesbarkeit erreichen sollen.
- --Der Hâkawâti ✉ 13:07, 29. Aug. 2009 (CEST)
- Ok, ich ändere zu
daToni.bereiteMahlzeitZu()
und bei der Wurst den Parameter Beilage und bei der Pizza keinen. --Wikiplex 14:08, 29. Aug. 2009 (CEST)
- Ok, ich ändere zu
Stimmt, super Beispiel, Wikiplex! So gesehen gar keine Hexerei. Ich geh jetz zum daToni Mahlzeit 84.113.215.146 13:26, 2. Okt. 2011 (CEST)
Java-Code in Abschnitt "Begriffsbedeutung" rausnehmen
Den würde ich gerne rausnehmen (da es nicht mehr sagt als der Fließtext und außerdem keine konkreten Produkte beinhaltet) und stattdessen das UML-Diagramm vergrößert (d.h. nicht als Thumbnail) nach vorne ziehen. Jemand was dagegen? --Wikiplex 17:25, 2. Sep. 2009 (CEST)
- Fänd ich gut. --Der Hâkawâti ✉ 23:09, 2. Sep. 2009 (CEST)
Abschnitt Nachteile
Den würde ich gerne, so wie er ist, ganz rausnehmen. (1) Unterklassenbildung ist nichts Böses, wenn die Anzahl der Klassen nicht explodiert. (2) Klar muss eine Klasse vorhanden sein, um eine statische Methode aufzunehmen. (3) Selbstverständlich kennt Java statische Methoden (z.B. Math.sqrt()). (4) GoF selbst kennt auch keine Nachteile, sondern nur Vorteile. --Wikiplex 15:18, 3. Sep. 2009 (CEST)
- Das seh ich anders.
- Patterns handeln immer von widerstrebenden Kräften, die ausgeglichen werden sollen. Demnach hat jedes Pattern Vor- und Nachteile.
- Unterklassenbildung ist nichts Böses, da hast du Recht. Eine Einschränkung hast du aber ja selbst schon genannt. Zudem entstehen hier - wie oft bei Patterns - "künstliche Klassen", also solche, die nicht aus dem Problem, sondern aus der Lösung kommen und deshalb auch erst im Entwurf und nicht schon in der Analyse eingeführt werden. Und künstliche Klassen sind erstmal schwieriger verständlich, weil nicht intuitiv herleitbar. Der Entwurf wird dadurch komplexer. Das ist übrigens allgemein ein Charakteristikum von Design Patterns. Wenn das intuitiv wäre, wäre das Muster nicht als solches erkennbar.
- Punkt ist hier, dass eine Klasse vorhanden sein muss, ein interface also nicht ausreicht.
- in Java-Klassen gibt es statische Methoden. Aber nicht in Interfaces.
- BTW: Alternative zur Fabrikmethode wäre DependencyInjection.
- --Der Hâkawâti ✉ 18:47, 3. Sep. 2009 (CEST)
- Welche Klassen sind für dich in dem Restaurant-Beispiel künstlich? Die abstrakten? Wenn das so ist: Es ist ja nur eine fixe Anzahl, die gemeinsame Wurzel aller konkreten Produkte. Daran liegt der eventuelle "Class-Bloat" nicht. Pro später im Framework zu erzeugenden Produkt braucht man eine eigene Klasse; darum kommt man schlecht drumrum, wenn man ein Framework für (noch unbekannte) Produkte schreiben will. Oder doch? Anders gefragt: Welche Klassen werden denn deiner Meinung nach in der Analyse eingeführt (weil sie intuitiv sind)? Und was ist eine DependencyInjection?
- Nachtrag: GoF (S. 109) nennt doch einen "möglichen" Nachteil, und zwar genau den mit der Unterklassenbildung, schränkt aber gleich wieder ein: "Subclassing is fine when the client has to subclass the Creator class anyway, but otherwise the client must deal with another point of evolution". Ich glaube mein Problem ist, dass mir kein Beispiel für "otherwise" einfällt. Und genau das, falls uns eins einfällt, sollte dann in den Punkt "Nachteile" rein! Grüße! --Wikiplex 09:05, 4. Sep. 2009 (CEST)
- Im Restaurant-Beispiel sind das alles natürliche Klassen. Hier konnten die Pattern-Klassen problemlos auf natürliche Klassen gemappt werden.
- Um zu zeigen, was ich mit "künstlichen Klassen" meine, eignet sich das Beispiel also nicht so gut. Am besten sieht mans, denk ich, am Visitor. Der Visitor hat (oft) keine natürliche Entsprechung. Die Visitor-Klasse wird im Design neu eingeführt. In der Analyse war sie noch nicht da. Machen wir mal ein Beispiel. Ein Programm soll eine Büchersammlung verwalten. Es wird also wohl unweigerlich eine Klasse Buch geben. Das ergibt sich direkt aus dem Problem, ist relativ unabhängig von der letztendlichen Realisierung und vollkommen intuitiv. Jedem, der sich das anguckt, wird sofort klar sein, warum es die Klasse Buch gibt. Wird jetzt in der Design-Phase ein BuchVisitor eingeführt, so ist diese Klasse technischen Ursprungs. Sie ist konkrete Realisierung und ergibt sich *nicht* direkt aus dem Problem, sondern aus der technischen Umsetzung. Das macht sie schwieriger verständlich.
- Wenn man Glück hat, kann man die Rolle, die eine künstliche Klasse übernimmt, einer natürlichen überklappern. Im UML-Diagramm wird dann also keine neue Klasse gezeichnet, sondern Beispielsweise eine bestehende, d.h. "natürliche" mit einem Stereotypen annotiert. Genau das ist hier beim Restaurant passiert. Man könnte der Klasse Mahlzeit den Stereotyp <<Product>> verpassen, der Pizza <<CocreteProduct>>, etc.
- Das Beispiel hier ist also eines, auf das der Nachteil nicht zutrifft. Jedoch kann es in anderen Situationen vorkommen, dass künstliche Klassen eingeführt werden.
- Hier ein Beispiel für den Subclassing-Nachteil: Angenommen ich wollte einen Blog-Reader schreiben, also eine Art Browser speziell für Blogs. Blog-Posts sollen der Performance wegen in einen Cache geschrieben werden. Jetzt wollen wir unterschiedliche Caches zur Verfügung stellen. Beispielsweise einer, der nur den RAM benutzt und einer, der auf die Platte auslagert. Angenommen wir wollen das mit ner Factory-Methode lösen. Ist ja kein Problem. BlogReader wird abstrakt und kriegt Subklassen RAMCachedBlogReader und HDCachedBlogReader. Wie man schon an der Benennung sieht, sind das künstliche Klassen. Damit hab ich jetzt aber - sofern ich keine Mehrfachvererbung zur Verfügung hab - meine einzige Möglichkeit der Subtypbildung verschenkt. Will ich jetzt beispielsweise einen BlogManager bauen, mit dem man Blogs nicht nur lesen, sondern auch schreiben kann, hab ich ein Problem. Von was soll ich jetzt ableiten? Von RAMCachedBlogReader oder von HDCachedBlogReader? Und selbst mit Mehrfachvererbung müsste ich pro Unterklasse von BlogReader eine BlogManager-Unterklasse einführen, was die Anzahl der Klassen weiter in die Höhe treibt. Mit DependencyInjection wär mir das nicht passiert...
- Dependency Injection ist ein nicht-GoF-Design-Pattern. Martin Fowler hat auch einen Artikel dazu. Auch, wenn ich den ServiceLocator kritischer sehe als Fowler und die IoC-Container wohl eher was für große Systeme sind, finde ich den Artikel trotzdem lesenswert. Er beschreibt ganz gut das Prinzip der Dependency-Injection, das sich natürlich unabhängig von den IoC-Containern einsetzen lässt. Oftmals halte ich diese Möglichkeit für besser als Fabrikmethoden.
- --Der Hâkawâti ✉ 10:34, 4. Sep. 2009 (CEST)
Vorteile: Complex.createFromRealAndImaginary() ist besser
Das Beispiel hat einen Haken: Beide Methoden Color.createFromRGB() und Color.createFromHSV() haben drei Parameter (RGB bzw. HSV). Die RGB-Werte sind alle ganzzahlig. Da der S-Wert in Color.createFromHSV() zwischen 0 und 1 liegt und somit als Fließkommazahl übergeben werden muss, würde es in Sprachen wie C++, Java und C# ausreichen, einen Konstruktor zu überladen. Da käme man also um die Fabrikmethoden rum.
Ein besseres Beispiel ist das Erzeugen einer komplexen Zahl, einmal aus Real- und Imaginärteil, einmal aus Polarkoordinaten (Winkel und Betrag). Was denkt ihr? Vorschläge zur Bennenung der Methoden? --Wikiplex 17:38, 8. Sep. 2009 (CEST)
- RGB und HSB kann man jeweils als drei Floats übergeben. Von daher hat man wieder die Notwendigkeit. Das ist auch nicht ganz an den Haaren herbeigezogen, weil es IIRC in OpenGL genau so gemacht wird. Gegen das Beispiel mit den Komplexen Zahlen hab ich aber auch nix. Außer natürlich, dass createFromRealAndImaginary ein scheußlich langer Bezeichner ist. Aber lieber lang als schlecht lesbar. BTW: createFromHSV() stimmt so nicht ganz. Auch, wenn das Lemma HSV heißt, so ist HSV mehrdeutig, da das HSB und HSL bezeichnen kann. --Der Hâkawâti ✉ 20:00, 8. Sep. 2009 (CEST)
- Ich verstehe nicht, warum HSV mehrdeutig ist. HSV-Farbraum definiert HSV doch eindeutig und gibt einen Umrechnungsalgorithmus HSV <-> RGB an. Hmmm, in dem Algorithmus sind RGB auch aus [0,1]. Dann ist der ganze Diskussionspunkt wohl hinfällig und das Beispiel hat keinen Haken. (Ich kannte RGB in allen Aufrufen halt nur als Integer aus [0,255].) Von HSB habe ich übrigens vor dem Lesen des HSV-Artikels noch nie was gehört; ich denke schon, dass HSV der bekanntere Begriff ist. --Wikiplex 12:26, 9. Sep. 2009 (CEST)
- *nochmal liest* OK hast Recht. Ich hatte irgendwie herausgelsen, dass HSV ein Überbegriff für HSB und HSL wäre. War aber Blödsinn... --Der Hâkawâti ✉ 13:04, 9. Sep. 2009 (CEST)