Markus: Fabrikmethoden

Hallo zusammen,

ich muss morgen ein referat über Fabrikmethoden halten.
Ich hab mir schon sämpliche Seiten in google durchgelesen. Aber so
richtig kapier ich das Thema nicht.

Wäre voll nett von euch wenn mir das einer von euch an einem einfachen
Beispiel erklären könnte.

Vielen Vielen Dank im Vorraus

Markus

  1. Lieber Markus,

    ich muss morgen ein referat über Fabrikmethoden halten.

    und seit wann hast Du Zeit dafür...? *g*

    Liebe Grüße aus Ellwangen,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. Seit 3 Tagen. Das ganze soll kein großer Vortrag werden eher
      ein 2 min Vortrag.
      Aber ich wollte das ganze halt gerne an Hand eines Beispiels erklären.

      1. Hi,

        dann versuch es in RL (Real Life) zu übertragen. Was machen Fabriken für gewöhnlich? Sie produzieren Objekte, bestimmte Objekte. Eine Dönerfabrik zum Beispiel Dönerfleisch, eine Spielzeugfabrik zum Beispiel Holzklötze (ohne sonstige sonderliche Funktionsmerkmale) oder Plüschtiere.

        In OO übertragen ist eine Factory ein oft eine Klasse die Methoden zur Produktion (Instantzierung) andererer Klassen (Objekte) anbietet.

          
        class MyFactory  
        {  
           // das ist eine Fabrikmethode, die ein Objekt vom Typ MyObject prodzuiert  
           MyObject CreateMyObject()  
           {  
             return new MyObject();  
             // oder  
             return MyObject.CreateFromContext();  
           }  
        }  
        
        

        Factory-Methoden oder Fabrik-Methoden können aber auch zum Bleistift auch direkt auf dem eigentlich Objekt definiert werden, dann meistens statisch:

          
        class MyObject  
        {  
           // das ist eine statische Fabrikmethode, die sich selbst prodzuiert  
           static MyObject CreateFromContext()  
           {  
             // erzeuge z.b. eine neue Instanz von MyObject, setze Properties und gib sie zurück  
             MyObject emmo = new MyObject();  
             // emmo.MyProperty = "HelloWorld";  
             // emmo.Initialize();  
             return emmo;  
           }  
        }  
        
        

        Du standardisierst dadurch die Instanzierung von deinen Objekten und kannst Regeln für selbige einfliessen lassen und deren Komplexität dann in der Fabrikmethode verstecken. Ansonsten hast du vielleicht viele wiederkehrende Codeblöcke à la

          
        {  
          // das ist oft redundant  
          MyObject emmo = new MyObject();  
          emmo.MyProperty = "HelloWorld";  
          emmo.Initialize();  
          
          // und hier fängst an mit dem Objekt die eigentliche Arbeit zu machen  
          emmo.DoMyWork("Hello World");  
        }  
        
        

        Wenn du im Web nach Patterns suchst oder "Erich Gamma" wirst du sicher einiges an Literatur finden. Unter anderem gibt es auch im Archiv des Forums dazu Threads. :)

        Ciao, Frank

        1. echo $begrüßung;

          Du standardisierst dadurch die Instanzierung von deinen Objekten und kannst Regeln für selbige einfliessen lassen und deren Komplexität dann in der Fabrikmethode verstecken. Ansonsten hast du vielleicht viele wiederkehrende Codeblöcke à la

          {
            // das ist oft redundant
            MyObject emmo = new MyObject();
            emmo.MyProperty = "HelloWorld";
            emmo.Initialize();

          // und hier fängst an mit dem Objekt die eigentliche Arbeit zu machen
            emmo.DoMyWork("Hello World");
          }

            
          Meinst du nicht, dass das eine Aufgabe für den Konstruktor wäre?  
            
          Ich hätte als Beispiel eher sowas gebracht: ohne Factory  
            
            wenn mysql  
              db = new mysqlDB  
            wenn oracle  
              db = new oracleDB  
            sonst  
              db = new sonstDB  
            
          mit Factory:  
            
            db = DB.factory('mysql')  
            oder  
            db = DB.factory('oracle')  
            
            
          echo "$verabschiedung $name";
          
          1. Hallo dedlfix

            ich blick durch dein Beispiel nicht wirklich durch
            wie meinste denn das?

            mit Factory:

            db = DB.factory('mysql')
              oder
              db = DB.factory('oracle')

            BZW was hab ich jetzt für Vorteile?

            1. echo $begrüßung;

              ich blick durch dein Beispiel nicht wirklich durch
              wie meinste denn das?

              mit Factory:

              db = DB.factory('mysql')
                oder
                db = DB.factory('oracle')

              BZW was hab ich jetzt für Vorteile?

              Beispielsweise braucht deine Anwendung Datenbankzugriff. Nun gibt es für die verschiedenen Systeme unterschiedliche APIs (Programmierschnittstellen), jeder Hersteller kocht da sein eigenes Süppchen. Um den Zugriff zu vereinheitlichen erstellt man sich eine Datenbankabstraktionsschicht. Die besteht aus einer Grund-Klasse für die allgemeinen Funktionen. Erweitert wird sie jeweils von auf das jeweilige System spezialisierte Klassen. Du hast also neben der Klasse DB auch eine DB_mysql und eine DB_oracle. Die Fabrik wählt nun anhand deines übergebenen Parameters aus, welche von DB abgeleitete Klasse sie nun instantiieren soll. Ansonsten müsstest du selbst entscheiden, welche spezialisierte Klasse zu instantiieren ist.

              echo "$verabschiedung $name";

            2. Hallo Markus,

              ich blick durch dein Beispiel nicht wirklich durch
              wie meinste denn das?

              mit Factory:

              db = DB.factory('mysql')
                oder
                db = DB.factory('oracle')

              BZW was hab ich jetzt für Vorteile?

              In dem Beispiel geht es darum, Klassen für den Datenbankzugriff zu erstellen. Wenn man mehrere Datenbanktypen (MySQL, PostgreSQL, Oracle, XML-Dateien, wasauchimmer) unterstützten will, verwendet man dafür z.B. Unterklassen einer abstrakten Klasse, also z.B.

              abstract class DB {...}
              class MySQLDB extends DB {...}
              class PostgreSQL extends DB {...}
              usw.

              Wenn jetzt ein Objekt für den Datenbankzugriff erstellt werden soll, muss erst überprüfen werden, welche konkrete Klasse instanziiert werden soll:

              if {config.dbtype == 'mysql') {
                 db = new MySQLDB();
              elseif {config.dbtype == 'postgresql') {
                 db = new PostgreSQL();
              } usw.

              Genau diese Aufgabe kapselt man jetzt in einer Factory-Methode:

              class DB {
              ...
                  static AbstractDB factory(String dbtype) {
                     if (dbtype == 'mysql')
                        db = new MySQLDB();
                     } ...
                     return db;
                  }
              ...
              }

              Diese Factory-Methode ruft man nun auf, um eine konkrete Instanz einer DB-Unterklasse zu erzeugen:

              db = DB.factory(config.dbtype);

              Auf den ersten Blick erscheint das unnötig kompliziert, aber es bringt einige Vorteile. Dadurch, dass die Logik zur Entscheidung welche konkrete Klasse verwendet werden soll an einer Stelle gespeichert ist, muss nur diese Stelle verändert werden, wenn neue Datenbanktypen hinzugefügt werden sollen. Außerdem braucht derjenige, der eine Datenbankklasseninstanz erzeugt gar nicht zu wissen, von welchem Typ diese Datenbank ist. Im obigen Beispiel wird z.B. einfach der Wert aus der Konfiguration durchgereicht.

              Schöne Grüße,

              Johannes

          2. Hi,

            nicht wirklich bzw. unbedingt. Es war nur einfach zufällig gewählter Pseudocode.

            Ich benutze hier (sehr erfolgreich nebenbei bemerkt) eine selbstgeschriebene XmlObjectFactory, die entweder Objekte ganz ohne Konstruktor-Unterstützung erzeugt via Xml-Serialisierung oder Propertywerte anhand von konfiguierten Werten in einer Xml-Datei setzt.
            Das ganze ist ein Satz statischer Methoden auf einer Basisklasse von der mein Objekt erbt. (z.b. CreateFromContext ...) Diese statischen Methoden sind die Fabrikmethoden. Sie benutzen dann eine AbstractFactory, welche die Xml Deserialisierung vornimmt. usw.

            Dein Beispiel der Factory wäre imho schon eine AbstractFactory, die Abstrahierung wäre "db", was entweder eine konkrete mysqlDB oder oracleDB oder sonstDB sein könnte.

              
            Spielzeug s = SpielzeugFabrik.Produce("Plüschtier");  
            if(!s.LookNice) s.Kill();  
            
            

            Warum Factory-Methods performance-kritisch sein können, kann man nicht pauschal diskutieren, schon gar nicht beantworten. Es kommt auf die Umstände an. Auch das Aufrufen des Konstruktors kann je nach Context performance-kritisch sein ;)

            Cheers, Frank

        2. Hi vielen Dank für deine ausführliche Antwort. Hat mir sehr geholfen.

          Eine Frage hätte ich noch.
          Hab eben gelesen das Fabrikmethoden den Code bzw das Programm verlangsamen können? Simmt das? Warum ist das so?

          Vielen Dank nochmal
          Markus

  2. Wäre voll nett von euch wenn mir das einer von euch an einem einfachen
    Beispiel erklären könnte.

    http://de.wikipedia.org/wiki/Fabrikmethode - bin ja selbst kein "OO-Guru", aber da scheint doch eine zusätzliche Abstraktionsebene vorzuliegen, die keine Klassen implementieren.

    Eine Organisationsform so zu sagen, eine zusätzliche Schicht, Beispiele im o.g. Webverweis...

  3. Hej,

    auch wenn du schon sehr gute Antworten bekommen hast, so würde ich in dem Zusammenhang noch ganz gerne das Kapitel Factory Methods (pdf) des Java Design Patterns Companion empfehlen. Da is auf 7 Seiten alles wichtige mit Code Beispielen erklärt. Was da steht (bis auf den Code *g*) gilt natürlich auch für alle anderen OO basierten Programmiersprachen.

    Beste Grüße
    Biesterfeld

    --
    Art.1: Et es wie et es
    Art.2: Et kütt wie et kütt
    Art.3: Et hätt noch immer jot jejange
    Das Kölsche Grundgesetz