Diskussion:Fabrikmethode

aus Wikipedia, der freien Enzyklopädie
Letzter Kommentar: vor 12 Jahren von 84.113.215.146 in Abschnitt Beispiele
Zur Navigation springen Zur Suche springen

statische FabrMethode[Quelltext bearbeiten]

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[Quelltext bearbeiten]

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[Quelltext bearbeiten]

  • 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)Beantworten
Guck mal aufs Datum. Das ist wohl längst überholt... -- Der Hâkawâti 18:29, 26. Aug. 2009 (CEST)Beantworten

Verständnisfrage zum UML-Diagramm[Quelltext bearbeiten]

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)Beantworten
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)Beantworten
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)Beantworten

Sinn fehlt[Quelltext bearbeiten]

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)Beantworten

Bildbeschreibung fehlt bei [[Bild:Fabrikmethode.png]][Quelltext bearbeiten]

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: und Image: in Datei:.
  • 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)Beantworten

Ist erledigt. Kann man diesen Punkt jetzt aus der Diskussion löschen? --Wikiplex 11:07, 27. Aug. 2009 (CEST)Beantworten

Beispiele[Quelltext bearbeiten]

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)Beantworten

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)Beantworten

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)Beantworten
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)Beantworten
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)Beantworten
  • 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 sich aufnehmeBestellung() bescheuert anhört, hast du ja selbst schon gemerkt. Was aber ist der Unterschied zu zubereiteMahlzeit()? 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 zu Bezeichner = 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.
--Der Hâkawâti 13:07, 29. Aug. 2009 (CEST)Beantworten
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)Beantworten

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)Beantworten

Java-Code in Abschnitt "Begriffsbedeutung" rausnehmen[Quelltext bearbeiten]

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)Beantworten

Fänd ich gut. --Der Hâkawâti 23:09, 2. Sep. 2009 (CEST)Beantworten

Abschnitt Nachteile[Quelltext bearbeiten]

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)Beantworten

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)Beantworten
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)Beantworten
  • 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)Beantworten

Vorteile: Complex.createFromRealAndImaginary() ist besser[Quelltext bearbeiten]

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)Beantworten

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)Beantworten
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)Beantworten
*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)Beantworten