# Unterschied Factory und Abstract Factory?



## EOB (13. Sep 2006)

hi, ich schnall den unterschied noch nicht so ganz. eine factory ist doch zum beispiel sowas hier:



```
public class MyFactory{
    private MyFactory(){}

    public static EinInterfaceTyp createInstance(String value){
        if(value.equals("1"))
            return new EinInterfaceImplementierung1();
        if(value.equals("2"))
            return new EinInterfaceImplementierung2();

       //und so weiter
      
}
```

die konkreten implementierungen werden also an einer stelle erstellt. die vorteile liegen auf der hand. wie ist das jetzt aber mit der abstract factory? die soll ja eine stufe abtrakter sein? ich hab mir schon 2 tuts angesehen, aber gebracht hats nix :-|.


danke!!


----------



## Anmeldeboykottierer (13. Sep 2006)

Hi,
eigentlich ist es ganz einfach, eine Abstrakte Fabrik ist eine Fabrik für Fabriken. 
Du meintest ja, dass der Vorteil einer Fabrik auf der Hand liegt, jetzt kannst du aber auch mehr als eine Fabrik haben. Typischerweise spricht man jetzt von einer Klasse von Fabriken oder einer Familie oder so.
Jedenfalls erzeugt eine Fabrik etwas konkretes und initialisiert dies usw. 
Eine Abstrakte Fabrik erzeugt dir hingegen eine konkrete Fabrik.

Hoffe es ist grob klar.

Die Motivation ist dabei eigentlich die gleiche wie bei der normalen Fabrik, nur  wie du schon sagtest etwas abstrakter.

Gruß Der Anmeldeboykottierer


----------



## EOB (13. Sep 2006)

heisann, verstehe. wir sind hier die einzigesten, die sowas diskutieren . hast du mal ein einfaches beispiel?

*EDIT:* mal der code hier. da ist ja dann datamanager die abstrakte fabrik, oder? denn hier werden ja local oder remote returnt. aber dann muessten ja local oder remote factories sein  ???:L ?


```
class DataInfo {}
interface Local {
  DataInfo[] loadDB(String filename);
}

interface Remote extends Local{
  void connect2WWW(String url);
}

class LocalMode implements Local {
  public DataInfo[] loadDB(String name) {
    System.out.print("Load from a local database ");
    return null;
  }
}

class RemoteMode implements Remote {
  public void connect2WWW(String url) {
    System.out.println("Connect to a remote site ");
  }
  public DataInfo[] loadDB(String name) {
     System.out.println("Load from a remote database ");
     return null;
  }
}

// The Abstract Factory
interface ConnectionFactory {
  Local getLocalConnection();
  Remote getRemoteConnection();
}

class DataManager implements ConnectionFactory {
    boolean local = false;
    DataInfo[] data;
    //...
    public Local getLocalConnection() {
        return new LocalMode();
    }
    public Remote getRemoteConnection() {
        return new RemoteMode();
    }
    public  void loadData() {
         if(local){
            Local conn = getLocalConnection();
            data = conn.loadDB("db.db");
         }else {
            Remote conn = getRemoteConnection();
            conn.connect2WWW("www.some.where.com");
            data = conn.loadDB("db.db");
         }
         
     }
	 // work on data 
   
    public void setConnection(boolean b) {
       local = b;
    }
}

//Use the following Test class to test the above classes
class Test {
    public static void main(String[] args) {
        DataManager dm = new DataManager();
        DataInfo[] di = null;
        String dbFileName = "db.db";
        if (args.length == 1) {
            //assume local is set to true
	    dm.setConnection(true);
            LocalMode lm = (LocalMode)dm.getLocalConnection(); 
	    di = lm.loadDB(dbFileName); 
        } else {  
           //Note: dm.local = false is default setting
           RemoteMode rm = (RemoteMode)dm.getRemoteConnection();
           rm.connect2WWW("www.javacamp.org/db/");
           di = rm.loadDB(dbFileName); 
        }
        //use one set of methods to deal with loaded data.
        //You don't need to worry about connection from this point.
        //Like di.find(), di.search() etc.
    }
}
```

danke!


----------



## Anmeldeboykottierer (13. Sep 2006)

Hm,
da bin ich mir jetzt nicht ganz so sicher. Ich hätte jetzt gesagt, dass eine Abstrakte Fabrik hier von dem konkreten abstrahiert. Local und remote sind ja eigentlich unterschiedliche Typen. Du hättest eher etwas abstrakt die Funktionalität, die dir eine Fabrik bietet:


```
interface Product;

inferface Factory {
  public Product produceProduct();
}

interface AbstractFactory {
  public Factory produceFactory();
}
```

Wobei du hier natürlich sinnvoller vorgehen solltest (schlechtes Beispiel). Jedenfalls könnte dein Abstrakte Fabrik hier Instanzen zur Verfügung stellen, die ein Fabrik-Interface implementieren (bzw. eine abstrakte Klasse). Damit kansnt du dann von der eigentlichen Fabrik abstrahieren.

Klauen wir uns doch mal ein Beispiel von Wikipedia:
Nimm das gute Beispiel GUIs mit Skin. Jenachdem welchen Skin du verwenden möchtest, wirst du eine andere Fabrik verwenden wollen. Jede Fabrik erzeugt für ein bestimmten Skin eine bestimmte GUI. Warum du eine Fabrik nimmst ist klar, da kannst du dann die einzelne Elemente der GUI entsprechend produzieren und zusammenfügen, initialisieren usw. 
Ja, da der Benutzer die Wahl der GUI hat, kannst du also mehr als ein Fabrik benötigen, davon abstrahiert dann einfach die abstrakte Fabrik. Jede Fabrik stellt die selben Methoden zur Verfügung, also erzeugst du die Fabrik abstrakt (konkrete Instanz, aber du arbeitest mit einem ADT).

Ja, das ist (so wie ich es verstanden habe) der Sinn einer abstrakten Fabrik. Letztlich ist es also auch nur eine Fabrik, das besondere ist nur, das hier auch Fabriken erzeugt werden.



> heisann, verstehe. wir sind hier die einzigesten, die sowas diskutieren


Die anderen melden sich bestimmt noch. Entweder (mangels rotem Kasten oder ähnlichem) zwischen deinem letzten Beitrag und dem hier oder spätestens wenn sie diesen Beitrag sehen und korrigieren ;-)


----------



## SnooP (13. Sep 2006)

Anmeldeboykottierer hat gesagt.:
			
		

> Die anderen melden sich bestimmt noch. Entweder (mangels rotem Kasten oder ähnlichem) zwischen deinem letzten Beitrag und dem hier oder spätestens wenn sie diesen Beitrag sehen und korrigieren ;-)



Nö... - passt doch schon alles oder?  ... das Widget-Beispiel ist eigentlich so das Gängigste und auch im Buch von Erich Gamma und Co. unter AbstractFactory zu finden. Die Idee ist unterschiedliche Möglichkeiten für die Erstellung von Klassen gleichen Typs (Abstrakte Klasse oder Interface) zu bekommen... dazu gibt es eine abstrakte Fabrikklasse die genutzt werden kann für versch. Implementierungen der Fabrik, die wiederum alle aufgrund eines createXY Methodenaufrufs andere Objekte erzeugen...

Ob man sowas braucht, ist im Einzelfall abzuklären, denk ich... - grundsätzlich spricht aber nichts dagegen alle Factories auf die Möglichkeit der Erweiterung hin zu optimieren, sprich man hat grundsätzlich eine AbstractFactory die verwendet wird... falls sich dann später andere Szenarien ergeben, wo andere Objektarten erstellt werden sollen, kann einfach die konkrete Factory ausgetauscht werden und schwupp es funnzt


----------



## EOB (13. Sep 2006)

hi, also ist eine abstrakte fabrik keine fabrik fuer fabriken, sondern lediglich eine schnittstelle fuer fabriken mit den selben inhalten, oder besser produkt/objektfamilien? ich dachte jetzt erst, dass eine abstrakte fabrik eben fabriken anlegt, welche dann ihren dienst machen. ist ja aber nicht so. man hat also immer eine abstrakte fabrik (interface oder abtrakte klasse mit abtrakten methoden), in der art:


```
public interface AbstractGameFactory {
      public Player createPlayer();
      public  GameField createGameField();                       
}
```

dann hab ich klassen, die das implementieren, also so hier:


```
public class TicTacToeFactory implements AbstractGameFactory{
     //implementierungen der methoden zum erzeugen der konkreten objekte

}

public class ChessFactory2 implements AbstractGameFactory{
     //implementierungen der methoden zum erzeugen der konkreten objekte

}
```

in den implementierungen wird dann eben festgelegt, was erzeugt wird.in dem fall, eben was fuer ein player und was fuer ein spielfeld. player und gamefield sind dann wiederum interfaces. also in dem fall ist die objektfamilie das spiel, richtig?


*EDIT: * ich denke, immer eine abstrakte fabrik zu haben, haut nicht hin, denn was sollen die createXY methoden dann zurueckliefern?

-->

```
interface AbtractFactory{
     public ??????? createXY();
}
```


gruesse


----------



## byte (13. Sep 2006)

Mørketid hat gesagt.:
			
		

> hi, also ist eine abstrakte fabrik keine fabrik fuer fabriken, sondern lediglich eine schnittstelle fuer fabriken mit den selben inhalten, oder besser produkt/objektfamilien?



Richtig. Die abstrakte Fabrik deklariert lediglich die gemeinsame Schnittstelle für alle konkreten Fabriken, also Methoden, die konkrete Objekte (einer Produktfamilie) erzeugen.


----------



## EOB (13. Sep 2006)

hi, also so? die produktfamilie waeren dann die server, korrekt?


```
interface Server{
....
}

class Server1 implements Server{...}
class Server2 implements Server{...}
class Server3 implements Server{...}

interface AbtractServerFactory{
    public Server createServer();
}

class Server1Factory implements AbstractServerFactory{
    public Server createServer(){
        return new Server1();
    }
}

....
```

die konkreten fabriken erzeugen dann also jeweils ein objekt von einer der serverimplementierungen?

danke


----------



## byte (13. Sep 2006)

You got it.


----------



## alehandro (13. Sep 2006)

Mørketid hat gesagt.:
			
		

> hi, also so? die produktfamilie waeren dann die server, korrekt?
> 
> 
> ```
> ...


ich glaibe in diesem Beispiel bringt Dir Abstract Factory nichts Neues, was dir bereits Factory Method sowieso gibt.
ich versuche es von scratch zu erklären:
1. Factory Method: gibt Dir eine Anstraktion über die zu erstellenden Produkte. (welcher genau erstellt werden soll weiss die Factory)
2. Abstract Factory: hier hast Du zwei Abstraktionen. Eine abstrahiert von den Produkten, die Zweite abstrahiert die Factory selbst. D.h. in deinem Programm sprichst Du nicht direkt eine gezielte Factory, sondern über eine Abstraktion. das Programm weist somit in Bezug auf die Factory bereits eine Laufzeit-Erweiterbarkeit auf.
Wozu ist das gut: das Beispiel von Anmeldeboykottierer paar posts weiter oben ist glaube ich anschauend um den Nutzen zu begreifen.


----------



## byte (13. Sep 2006)

```
interface Foo {...}
interface Bar {...}

class Foo1 implements Foo {...}
class Foo2 implements Foo {...}

class Bar1 implements Bar {...}
class Bar2 implements Bar {...}

interface AbstractFooBarFactory{
    public Foo createFoo();
    public Bar createBar();
}

class FooBar1Factory implements AbstractFooBarFactory{
    public Foo createFoo(){ return new Foo1(); }
    public Bar createBar(){ return new Bar1(); }
}

class FooBar2Factory implements AbstractFooBarFactory{
    public Foo createFoo(){ return new Foo2(); }
    public Bar createBar(){ return new Bar2(); }
}
```


----------



## EOB (14. Sep 2006)

alles klar...denk ich


----------



## EOB (14. Sep 2006)

oder doch nicht...ist da nicht ein unterschied zwischen


```
interface Foo {...}
interface Bar {...}

class Foo1 implements Foo {...}
class Foo2 implements Foo {...}

class Bar1 implements Bar {...}
class Bar2 implements Bar {...}

interface AbstractFooBarFactory{
    public Foo createFoo();
    public Bar createBar();
}

class FooBar1Factory implements AbstractFooBarFactory{
    public Foo createFoo(){ return new Foo1(); }
    public Bar createBar(){ return new Bar1(); }
}

class FooBar2Factory implements AbstractFooBarFactory{
    public Foo createFoo(){ return new Foo2(); }
    public Bar createBar(){ return new Bar2(); }
```

und zb dem hier:


```
/*
* GUIFactory example
*/

public abstract class GUIFactory {
   public static GUIFactory getFactory() {
        int sys = readFromConfigFile("OS_TYPE");
        if (sys == 0) {
            return(new WinFactory());
        } else {
            return(new OSXFactory());
        }
   }
   public abstract Button createButton();
}

class WinFactory extends GUIFactory {
    public Button createButton() {
        return(new WinButton());
    }
}

class OSXFactory extends GUIFactory {
    public Button createButton() {
        return(new OSXButton());
    }
}

public abstract class Button  {
    private string caption;
    public abstract void paint();
    
    public String getCaption(){
        return caption;
    }
    public void setCaption(String caption){
        this.caption = caption;
    }
}

class WinButton extends Button {
    public void paint() {
       System.out.println("I'm a WinButton: "+caption);
    }
}

class OSXButton extends Button {
    public void paint() {
       System.out.println("I'm a OSXButton: "+caption);
    }
}

public class Application {
    public static void main(String[] args) {
        GUIFactory aFactory = GUIFactory.getFactory();
        Button aButton = aFactory.createButton();
        aButton.setCaption("Play");
        aButton.paint();
    }
   
}
```

der zweite code ist ja ne factory fuer factories und der erste ehier wieder eine gemeinsame schnittstelle? hm...wie denn nun? vermutlich ist hier die nutzung wiedermal auslegungssache...vlt. gibts ja 2 arten von abstract factories  ???:L .

ich tendiere ja eher zur 2ten version, da mir das doch eher das richtige zu sein scheint. man hat eben zuerst eine abstraktion ueber die fabriken, welche allerdings eben alle zu einem 'thema' gehoren, naemlich eben os zeug und dann nochmal ueber die normalen fabriken, die dann eben die eigentlichen objekte erstellen.

gruesse


----------

