620 Stimmen

Was sind die Unterschiede zwischen den Entwurfsmustern Abstract Factory und Factory?

Ich weiß, dass es viele Beiträge über die Unterschiede zwischen diesen beiden Mustern gibt, aber es gibt ein paar Dinge, die ich nicht finden kann.

Aus dem, was ich gelesen habe, sehe ich, dass die Fabrik-Methode Muster ermöglicht es Ihnen zu definieren, wie ein einzelnes konkretes Produkt zu schaffen, sondern versteckt die Umsetzung aus dem Client, wie sie ein generisches Produkt sehen wird. Meine erste Frage bezieht sich auf die abstrakte Fabrik. Erlaubt sie die Erstellung von Familien konkreter Objekte (die von der verwendeten Fabrik abhängen können) und nicht nur eines einzelnen konkreten Objekts? Gibt die abstrakte Fabrik nur ein sehr großes Objekt zurück oder viele Objekte, je nachdem, welche Methoden Sie aufrufen?

Meine letzten beiden Fragen beziehen sich auf ein einziges Zitat, das ich nicht ganz verstehe und das ich an zahlreichen Stellen gesehen habe:

Ein Unterschied zwischen den beiden ist, dass mit dem abstrakten Fabrikmuster, eine Klasse die Verantwortung für die Objektinstanziierung an ein anderes Objekt durch Komposition delegiert, während das Factory Methoden-Muster Vererbung verwendet und eine Unterklasse für die gewünschte gewünschten Objektinstanziierung.

Ich verstehe, dass das Factory-Methodenmuster eine Creator-Schnittstelle hat, die den ConcreteCreator wissen lässt, welches ConcreteProduct er instanziieren soll. Ist es das, was mit der Verwendung von Vererbung zur Handhabung der Objektinstanziierung gemeint ist?

Wie genau delegiert das Muster der abstrakten Fabrik die Verantwortung für die Instanziierung eines Objekts über die Komposition an ein anderes Objekt, um sich auf dieses Zitat zu beziehen? Was ist damit gemeint? In meinen Augen sieht es so aus, als ob das Abstract Factory-Muster auch die Vererbung nutzt, um den Konstruktionsprozess durchzuführen, aber auch hier bin ich noch dabei, etwas über diese Muster zu lernen.

Für jede Hilfe, insbesondere bei der letzten Frage, wäre ich sehr dankbar.

686voto

Tom Dalling Punkte 22462

Der Unterschied zwischen den beiden

Der Hauptunterschied zwischen einer "Fabrikmethode" und einer "abstrakten Fabrik" besteht darin, dass die Fabrikmethode eine Methode und die abstrakte Fabrik ein Objekt ist. Ich glaube, viele Leute verwechseln diese beiden Begriffe und verwenden sie austauschbar. Ich erinnere mich, dass es mir schwerfiel, den Unterschied zu erkennen, als ich sie lernte.

Da die Factory-Methode nur eine Methode ist, kann sie in einer Unterklasse überschrieben werden, daher die zweite Hälfte Ihres Zitats:

... das Factory-Methoden-Muster verwendet Vererbung und verlässt sich auf eine Unterklasse um das gewünschte Objekt zu behandeln Instanziierung.

Das Zitat geht davon aus, dass ein Objekt die seine eigene Fabrikmethode hier. Das einzige, was den Rückgabewert ändern könnte, wäre daher eine Unterklasse.

Die abstrakte Fabrik ist ein Objekt, das über mehrere Fabrikmethoden verfügt. Betrachten Sie die erste Hälfte Ihres Zitats:

... mit dem Muster der abstrakten Fabrik, einer Klasse die Verantwortung für die Objektinstanziierung Instanziierung an ein anderes Objekt über Komposition ...

Was sie damit sagen wollen, ist, dass es ein Objekt A gibt, das ein Foo-Objekt erstellen möchte. Anstatt das Foo-Objekt selbst zu erzeugen (z.B. mit einer Factory-Methode), wird es ein verschiedene Objekt (die abstrakte Fabrik), um das Foo-Objekt zu erstellen.

Code-Beispiele

Um Ihnen den Unterschied zu verdeutlichen, sehen Sie hier eine Fabrikmethode im Einsatz:

class A {
    public void doSomething() {
        Foo f = makeFoo();
        f.whatever();   
    }

    protected Foo makeFoo() {
        return new RegularFoo();
    }
}

class B extends A {
    protected Foo makeFoo() {
        //subclass is overriding the factory method 
        //to return something different
        return new SpecialFoo();
    }
}

Und hier ist eine abstrakte Fabrik im Einsatz:

class A {
    private Factory factory;

    public A(Factory factory) {
        this.factory = factory;
    }

    public void doSomething() {
        //The concrete class of "f" depends on the concrete class
        //of the factory passed into the constructor. If you provide a
        //different factory, you get a different Foo object.
        Foo f = factory.makeFoo();
        f.whatever();
    }
}

interface Factory {
    Foo makeFoo();
    Bar makeBar();
    Aycufcn makeAmbiguousYetCommonlyUsedFakeClassName();
}

//need to make concrete factories that implement the "Factory" interface here

156voto

jgauffin Punkte 97446

Abstrakte Fabrik erstellt eine Basisklasse mit abstrakten Methoden, die Methoden für die zu erstellenden Objekte definieren. Jede Fabrikklasse, die die Basisklasse ableitet, kann für jeden Objekttyp ihre eigene Implementierung erstellen.

enter image description here

Fabrik-Methode ist nur eine einfache Methode, um Objekte in einer Klasse zu erstellen. Sie wird normalerweise im Aggregat Root hinzugefügt (Die Order Klasse hat eine Methode namens CreateOrderLine )

enter image description here

Abstrakte Fabrik

Im folgenden Beispiel entwerfen wir eine Schnittstelle, mit der wir die Erstellung von Warteschlangen von einem Nachrichtensystem entkoppeln können und somit Implementierungen für verschiedene Warteschlangensysteme erstellen können, ohne die Codebasis ändern zu müssen.

interface IMessageQueueFactory
{
  IMessageQueue CreateOutboundQueue(string name);
  IMessageQueue CreateReplyQueue(string name);
}

public class AzureServiceBusQueueFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new AzureMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new AzureResponseMessageQueue(/*....*/);
      }

}

public class MsmqFactory : IMessageQueueFactory
{
      IMessageQueue CreateOutboundQueue(string name)
      {
           //init queue
           return new MsmqMessageQueue(/*....*/);
      }

      IMessageQueue CreateReplyQueue(string name)
      {
           //init response queue
           return new MsmqResponseMessageQueue(/*....*/);
      }
}

Fabrik-Methode

Das Problem bei HTTP-Servern ist, dass wir immer eine Antwort auf jede Anfrage benötigen.

public interface IHttpRequest
{
    // .. all other methods ..

    IHttpResponse CreateResponse(int httpStatusCode);
}

Ohne die Factory-Methode wären die Benutzer des HTTP-Servers (d. h. die Programmierer) gezwungen, implementierungsspezifische Klassen zu verwenden, was den Zweck der IHttpRequest Schnittstelle.

Deshalb führen wir die Factory-Methode ein, damit auch die Erstellung der Antwortklasse abstrahiert wird.

概要

Der Unterschied besteht darin, dass die Verwendungszweck der Klasse, die eine Fabrikmethode enthält ist es nicht, Objekte zu schaffen , während eine abstrakte Fabrik nur zur Erstellung von Objekten verwendet werden sollte.

Bei der Verwendung von Factory-Methoden ist Vorsicht geboten, da es leicht zu einem Bruch des LSP kommen kann ( Liskov-Substitutionsprinzip ) beim Erstellen von Objekten.

144voto

Die Unterschiede zwischen den Entwurfsmustern AbstractFactory und Factory sind wie folgt:

  • Fabrik-Methode wird nur zur Erstellung eines Produkts verwendet, aber Abstrakte Fabrik geht es darum, Familien von verwandten oder abhängigen Produkten zu schaffen.
  • Fabrik-Methode Muster dem Client eine Methode zur Erstellung des Objekts zur Verfügung stellt, während im Fall von Abstrakte Fabrik sie stellen eine Familie von verwandten Objekten dar, die aus diesen Factory-Methoden bestehen können.
  • Fabrik-Methode Muster verbirgt die Konstruktion eines einzelnen Objekts, während Abstrakte Fabrik verbirgt die Konstruktion einer Familie verwandter Objekte. Abstrakte Fabriken werden in der Regel mit (einer Reihe von) Fabrikmethoden implementiert.
  • Abstrakte Fabrik Muster verwendet Komposition, um die Verantwortung für die Erstellung eines Objekts an eine andere Klasse zu delegieren, während Fabrik-Methode Das Entwurfsmuster verwendet Vererbung und stützt sich auf eine abgeleitete Klasse oder Unterklasse, um ein Objekt zu erstellen.
  • Die Idee hinter dem Fabrik-Methode Muster ist, dass es den Fall zulässt, dass ein Client nicht weiß, welche konkreten Klassen er zur Laufzeit erstellen muss, sondern lediglich eine Klasse erhalten möchte, die die Aufgabe erfüllt, während Abstrakte Fabrik Muster wird am besten verwendet, wenn Ihr System mehrere Produktfamilien erstellen muss oder Sie eine Bibliothek von Produkten bereitstellen wollen, ohne die Implementierungsdetails offenzulegen!

Implementierung des Factory-Methodenmusters: Factory Method UML

Implementierung des abstrakten Fabrikmusters:

Abstract Factory UML

91voto

jaco0646 Punkte 13032

Der Hauptunterschied zwischen Abstract Factory und Factory Method besteht darin, dass Abstrakte Fabrik wird durch Komposition implementiert aber Fabrikmethode wird durch Vererbung implementiert .

Ja, Sie haben richtig gelesen: Der Hauptunterschied zwischen diesen beiden Mustern ist die alte Komposition vs. Vererbung Debatte.

UML-Diagramme sind im (GoF-)Buch zu finden. Ich möchte Code-Beispiele bereitstellen, weil ich denke, dass die Kombination der Beispiele aus den ersten beiden Antworten in diesem Thread eine bessere Demonstration bietet als jede Antwort für sich. Außerdem habe ich bei den Klassen- und Methodennamen die Terminologie aus dem Buch verwendet.

Abstrakte Fabrik

  1. Der wichtigste Punkt, der hier zu beachten ist, ist, dass die abstrakte Fabrik ist. eingespritzt in den Client. Aus diesem Grund sagen wir, dass Abstract Factory durch Composition implementiert wird. Oft würde ein Dependency Injection Framework diese Aufgabe übernehmen, aber ein Framework ist nicht erforderlich für DI.
  2. Der zweite kritische Punkt ist, dass die Betonfabriken hier sind nicht Implementierungen von Factory-Methoden! Der Beispielcode für die Factory Methode wird weiter unten gezeigt.
  3. Der dritte Punkt schließlich ist die Beziehung zwischen dem Produkten: in diesem Fall die Ausgangs- und die Antwort-Queue. Eine konkrete Fabrik produziert Azure-Warteschlangen, die andere MSMQ. Die GoF bezeichnen diese Produktbeziehung als "Familie" und es ist wichtig zu wissen, dass dass Familie in diesem Fall nicht Klassenhierarchie bedeutet.

    public class Client { private final AbstractFactory_MessageQueue factory;

    public Client(AbstractFactory_MessageQueue factory) {
        // The factory creates message queues either for Azure or MSMQ.
        // The client does not know which technology is used.
        this.factory = factory;
    }
    
    public void sendMessage() {
        //The client doesn't know whether the OutboundQueue is Azure or MSMQ.
        OutboundQueue out = factory.createProductA();
        out.sendMessage("Hello Abstract Factory!");
    }
    
    public String receiveMessage() {
        //The client doesn't know whether the ReplyQueue is Azure or MSMQ.
        ReplyQueue in = factory.createProductB();
        return in.receiveMessage();
    }

    }

    public interface AbstractFactory_MessageQueue { OutboundQueue createProductA(); ReplyQueue createProductB(); }

    public class ConcreteFactory_Azure implements AbstractFactory_MessageQueue { @Override public OutboundQueue createProductA() { return new AzureMessageQueue(); }

    @Override
    public ReplyQueue createProductB() {
        return new AzureResponseMessageQueue();
    }

    }

    public class ConcreteFactory_Msmq implements AbstractFactory_MessageQueue { @Override public OutboundQueue createProductA() { return new MsmqMessageQueue(); }

    @Override
    public ReplyQueue createProductB() {
        return new MsmqResponseMessageQueue();
    }

    }

Fabrik-Methode

  1. Der wichtigste Punkt, der hier zu beachten ist, ist, dass die ConcreteCreator es den Kunden. Mit anderen Worten, der Client ist eine Unterklasse, deren Elternteil die factoryMethod() . Aus diesem Grund sagen wir, dass Factory Method wird durch Vererbung implementiert.
  2. Der zweite kritische Punkt ist die Tatsache, dass die Factory-Methode Muster nichts anderes ist als eine Spezialisierung des Template-Methoden Musters ist. Die beiden Muster haben eine identische Struktur. Sie unterscheiden sich nur unterscheiden sich nur im Zweck. Die Factory-Methode ist schöpferisch (sie baut etwas), während die Template-Methode verhaltensorientiert ist (sie berechnet etwas).
  3. Der dritte Punkt ist schließlich, dass die Creator (Elternteil) Klasse ruft ihre eigene factoryMethod() . Wenn wir entfernen anOperation() von der übergeordneten Klasse, so dass nur eine einzige Methode übrig bleibt zurücklässt, handelt es sich nicht mehr um das Factory Method-Muster. Mit anderen Worten, Factory Method kann nicht mit weniger als zwei Methoden in der der übergeordneten Klasse implementiert werden; und eine muss die andere aufrufen.

    public abstract class Creator { public void anOperation() { Product p = factoryMethod(); p.whatever(); }

    protected abstract Product factoryMethod();

    }

    public class ConcreteCreator extends Creator { @Override protected Product factoryMethod() { return new ConcreteProduct(); } }

Verschiedenes & Diverses Fabrikmuster

Beachten Sie, dass die GoF zwar zwei verschiedene Factory-Muster definieren, dies aber nicht die einzigen Factory-Muster sind, die es gibt. Sie sind nicht einmal unbedingt die am häufigsten verwendeten Factory-Muster. Ein berühmtes drittes Beispiel ist das Static Factory Pattern von Josh Bloch aus Effective Java. Das Buch Head First Design Patterns enthält noch ein weiteres Muster, das sie Simple Factory nennen.

Tappen Sie nicht in die Falle, anzunehmen, dass jedes Factory-Muster mit einem aus den GoF übereinstimmen muss.

46voto

Trying Punkte 13480

Abstract Factory ist eine Schnittstelle zur Erstellung verwandter Produkte, aber Factory Method ist nur eine Methode. Abstract Factory kann durch mehrere Factory-Methoden implementiert werden.

Abstract Factory UML

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X