Entwickler-Ecke

Programmierwerkzeuge - Factory-Pattern richtig verstanden?


ironhaert - Fr 20.08.10 15:09
Titel: Factory-Pattern richtig verstanden?
Hi miteinander,
ich wollte hiermit mal etwas in Erfahrung bringen:
Ich habe folgendes Klassendesign:
[url=http://img830.imageshack.us/i/unbenannthj.png/]user defined image[/URL]

Eine Klasse AbstractBaseType und darunter weitere Klassen CocreteTypX.
Die Basisklasse, enthält eine statische Methode, InstanceOf(objAssembly), welche ein Typ ihrer eigenen Klasse zurückgibt. Dabei ist zu beachten, dass sie einen Assembly übergeben bekommt, dessen Typ sie Instanziieren soll. Also in der Assembly ist je nach Fall bezogen, irgendein Untertyp dieser Basisklasse.
Die Methoden der Basisklasse Initialize und DoSomething virtuelle Methoden und stellen somit Polymorphie bereit. Das ist auch die Hauptaufgabe, der Abstrakten Klasse, die Unterklassen Fallbezogen instanziieren und ohne des Wissens des Typs, der Unterklasse, diese Funktionalität ausführen.

Nun habe ich hierzu ne allgemeine Frage:
Entspricht diese Implementierung noch einem der Patterns (Fabrikmethode oder abstrakte Fabrik)?
Tendeziell würde ich es unter der Fabrikenmethode aneigenen. Jedoch, ist der Unterschied in meinem Fall der, dass ich das Muster konkrete Implementiert habe. Also nicht Extra eine Erzeugerklasse für jeden Typ usw. (Sondern dies durch die Basisklasse Typspezifisch machen gelassen habe.
Zudem ist in der Fabrikenmethode die Objekterzeugung durch die Unterklassen gegeben und ich lasse mir den konkreten Typ der Unterklasse jedoch in der durch den Typ in der Assemly erzeugung und packe ihn dann in die Oberklasse um die Funktionaliät eines Unterklassentyps polymorph via Oberklasse bereitzustellen.

Eine abstrakte Fabrik ist jedoch auch ganz anders. Hm...
Was ist eure Meinung?

grüße ironhaert


delfiphan - Fr 20.08.10 19:14

Das Diagramm zeigt weder das einen noch das andere. Ich sehe vor allem überhaupt keine Methode, die irgend etwas "fabriziert".

Du sagst du hast eine statische Methode, die einen Klassentyp zurückgibt. Das ist dann keine Factory. Unter C# ist sowas übrigens gar nicht möglich (statische virtuelle Methoden). In Delphi ist's möglich und wird teilweise auch zusammen mit einem virtuelle Konstruktor verwendet.

Wofür Factory Method/Abstract Factory da ist:
Das Problem bei der Instanzierung ist, dass man immer den konkreten Typ haben muss (Delphi mit den Classtypes ist da etwas speziell). Die Factory Method und das Abstract Factory abstrahieren die Instanzierung von Klassen, sodass ein Code, der etwas instanzieren will, den Typ nicht direkt kennen muss.

Eine Factory Method ist praktisch jede Methode, die virtuel ist und sich nur mit der Instanzierung einer Klasse kümmert. Das Abstract Pattern verwendet Factory Methods für einen bestimmten Zweck. Dort geht es darum, verschiedene Objekte, die zusammengehören von einer Klasse erzeugen zu lassen. Du hast z.B. eine Factory, die graue Windows 95 Knöpfe, Listen und Checkboxen erstellen kann und eine weitere Factory, die glitzernde, animierte Windows 7 Knöpfe, Listen und Checkboxen erstellen kann. Am Anfang deines Programmes machst du eine If-Abfrage. Auf einem alten PC nimmst du die erste Factory mit den alten Knöpfen und bei einem neuen PC die zweite Factory. Die instanzierte Factory kannst du dann (im einfachsten Fall) als globale Variable dem Rest des Programmes zur Verfügung stellen. So müssen die dann selbst keine Fallunterscheidungen mehr machen.

Bei deinem Konstrukt mit der statischen InstanceOf und dem Assembly ist mir jetzt nicht klar, was du damit erreichen willst.


ironhaert - So 22.08.10 17:42

Hm... vielleicht hab ich mich nicht deutlich genug ausgedrückt.
Die statische (und nicht viruelle!) Methode InstanceOf(Assembly) in der Klasse AbstractBaseType erzeugt den Typ, welche innerhalb der Assembly steckt und ein Subtyp von AbstractBaseType ist; dieserabgeleitete Typ ist dann der Rückgabewert.
Dabei ist definiert, dass in der Assembly auch nur ein Typ existiert, welcher Subtyp der AbstractBaseType-Klasse ist.
Virtuell sind nun nur die Funktionen Initialize und DoSomething(). Diese stellen quasi die einheitliche Schnittstelle dar um einene genersichen Aufruf zu ermöglichen.

Ich will somit via Polymorphie die Funktionalität generisch und erweiterbar halten.
D.h. es ist generisch möglich(also durch bestimmung der Assembly), dass über die Basisklasse via Assembly die konkrete Ableitung der Unterklasse erhalte.
Die Unterklassen enthalten alle eine bestimmte Funktionalität, welche ich Fallabhänig benutzen möchte. Diese Fallunterscheidung erfolgt vorher durch Auswahl der Assembly.

Naja...mittlerweile bin ich auch schon zu der Erkenntnis gekommen, dass en Interface wohl sinnvoller gewesen wäre.
Aber da war irgendein Grund warum ich das damals nicht gemacht hatte.

Die Frage ist jetz nur, ob das noch etwas mit Factory Method/Abstract Factory zu tun hat.
Imho jein. :-) ..obwoh ich eher zu ja als nein tendiere...
Naja...irgendwie finde ich hats schon was mit einer Fabrikenmethode zu tun...ist nur ein bisschen anders angewendet. (Man müsste jetz das GoF-Buch da hamn und mal nachschuen, wie's die Leute genau definiert ham'n.

Hm..aber irgendwie bin ich jetz durcheinander gekommen.
Was ist dann der Vorteil einer Factory-Method? Wieso tut man das? Weil, für jeden Subtyp ne Extraklasse zu tun finde ich ein bisschen heftig.

Hm..ich glaub ich ziehe mir nochmal en paar Beispiele rein für das Pattern und tu sie mal versuchen durchzuführen und nach zu vollziehen.
Vielleicht ist in meinem speziellen Fall, das so wie ich's gelöst habe vollkommen i.O..


ironhaert - Mo 23.08.10 10:58

Moin,
so jetz nochmals weitere Infos:
Ich weiß nun wieder, warum Basisklasse Abstract ist und die "Quasifabrikmethode" sich als die InstanceOfMethode in der Basisklasse befindet.
Die Basisklasse "AbstractBaseType" wurde beabsichtigt Abstract Implementiert, da sie die "Megaschnittstelle" für die Subtypen sein soll.
Dafür müssen in der Basisklasse auch alle Methoden der Interfaces existieren, allerdings darf die Basisklasse die Interfaces NICHT IMPLEMENTIEREN!
Somit muss die Basisklasse auch die Methoden für die Schnittstelle1 beinhalten, das sind in der momentanen Version z.B. die beiden Methdoen Initilise und DoWork, ohne dabei vom Interface abegeleitet zu sein.

Nun kann die Schnittstelle erweitert und die alte Schnittstelle beibehalten werdenm indem man en 2. Interface erstellt, welche die neue Schnittstelle representiert. Diese Methoden müssen wiederum in der Basisklassse verfügbar gemacht werden.
In der Basisklasse werden nun alle Schnittstellen-Methoden als virtuell implementiert ohne wiederum die Klasse selbst von der Schnittstelle abzuleiten.
Für die Methoden in der Basisklasse soll hier jedoch eine Exception geworfen werden. Damit ist klar, dass die Basisklase keinen Aufrufe wirklich durchführen darf, sondern nur die Subtypen.
Der weitere Subtyp, welcher die neue Schnittstelle verwendet, wird nun von dieser abgeleitet.

Der große Vorteil ist hierbei, dass es nun möglich ist, auch verschiedene Schnittstellen durch die Basisklasse aufzurufen. Unterscheidbar ist dies durch die Überprüfung, welcher Schnittstellentyp ein Subtypobjekt implementiert und dadurch generisch aufgerufen werden(Daher darf die Basisklasse auch nicht die Interfaces implementieren, da sonst auch die Subtypen alle Interfaces enthalten.

Das ganze ist im folgenden Bild nochmal genauer verdeutlicht:
[url=http://img840.imageshack.us/i/unbenannt3e.png/]user defined image[/URL]

EDIT:
BTW, ich hab nen Fehler gemacht zweck Posting und muss mich im Thema Cross-Posting schuldig bekennen.
Tut mir leid -.- ich werds net wieder tun.
Wer noch andere Antworten über dieses Thema einsehen möchte, kann diese hier tun: http://www.mycsharp.de/wbb2/thread.php?threadid=87971


grüße ironhaert


delfiphan - Di 24.08.10 00:16

Was ist jetzt die Frage in dem Monolog oben? Am besten googlest du einfach das Pattern, in Wikipedia hat es bestimmt UML Diagramme. Bei konkreten Fragen können wir auch konkrete Antworten geben.

Wofür Factory-Method da ist habe ich doch oben geschrieben. Es geht darum, die Instanzierung von Instanz verschiedener konkreter Typen zu abstrahieren, sodass der konkrete Typ nicht bekannt sein muss, sondern je nach Fall unterschiedlich sein kann.


ironhaert - Fr 27.08.10 22:17

Hallo delfiphan,
das ganze sollte kein Monolog sein, sondern meine Implementierung nochmals genaustens erläutern.

Meine konkrete Frage ist im allerersten Post dargestellt:
Stellt die statische InstanceOf-Methode einen Fabrikenmethode dar?
bzw. Besteht eine gewisse ähnlichkeit mit der Fabrikenmethode?
bzw. Sind die Ziele die selben, wie die der Fabrikenmethode?


Deine Antwort, war Nein
Zitat:
Das Diagramm zeigt weder das einen noch das andere. Ich sehe vor allem überhaupt keine Methode, die irgend etwas "fabriziert".


Allerdings fabriziert die IntanceOf-Methode jedoch etwas und zwar einen Instanz eines Subtyps der Basisklasse zur Laufzeit durch den übergebenen Parameter. D.h, die Basisklass dient in meinem konkrete Fall auch als Fabrik? Richtig? Nur als generische Fabrik; nämlich aghänig, welche Subklasse benötigt wird. Das wird durch den Parameter bestimmt.

Das Wikibeispiel hab ich mir schon zig mal angeschaut und auch andere Beispiele für das Pattern.
Zeigen aber immer das selbe Bild. :-) ...ich verstehs wohl einfach nicht.
Zitat:

Es geht darum, die Instanzierung von Instanz verschiedener konkreter Typen zu abstrahieren, sodass der konkrete Typ nicht bekannt sein muss, sondern je nach Fall unterschiedlich sein kann.

Und das ist doch genau das, was meine Methode auch darstellt. Der konkrete Typ ist nicht bekannt sonder kann unterschiedlich sein. Die Fallunterscheidung erfolgt durch den Parameter.

Der große Vorteil hierbei finde ich, dass nicht extra zu jedem Subtyp eine weitere Klasse erezeugt werden muss.

Leider muss ich nun hier an dieser Stelle auf den X-Post eingehen:
zommi nanne folgende Punkte
* Instanzen unterschiedlicher Klassen über einheitliche Schnittstelle ansprechen
* Instanzen unterschiedlicher Klassen einheitlich erzeugen
Und in meinem Fall verwende ich beides.

schönes wochenende,
gruß ironhaert