13 Stimmen

Welche Methoden sollten in meiner DDD-Fabrikklasse enthalten sein?

Ich kämpfe, um zu verstehen, was meine Fabrik-Klasse in meinem DDD-Projekt tun sollte. Ja, eine Fabrik sollte für die Erstellung von Objekten verwendet werden, aber was genau sollte sie tun. Betrachten Sie die folgende Factory-Klasse:

    public class ProductFactory
    {
        private static IProductRepository _repository;

        public static Product CreateProduct()
        {
            return new Product();
        }

        public static Product CreateProduct()
        {
            //What else would go here?
        }

        public static Product GetProductById(int productId)
        {
            //Should i be making a direct call to the respoitory from here? 
            Greener.Domain.Product.Product p = _repository.GetProductById(productId);
            return p;
        }
    }

Sollte ich einen direkten Aufruf an das Repository aus der Fabrik heraus machen?

Wie sollte ich die Objekterstellung verwalten, wenn ich Daten aus einer Datenbank abrufe?

Was brauche ich, um diese Klasse vollständig zu machen, welche anderen Methoden sollte ich haben?

Sollte ich diese Klasse verwenden, um das Produktobjekt aus der Domäne und Repository von rechts zu erstellen?

Bitte um Hilfe!

1 Stimmen

Bauen Sie keine Repository-Logik in Ihre Fabrik ein.

13voto

Mark Rogers Punkte 93441

Sollte ich einen direkten Anruf bei das Repository aus der Fabrik machen?

Nein, verwenden Sie keine Fabrik, wenn Sie etwas abrufen, verwenden Sie eine Fabrik nur, wenn Sie sie zum ersten Mal erstellen.

Wie sollte ich die Erstellung von Objekten verwalten? wenn ich Daten aus einer Datenbank abrufe?

Übergeben Sie diese Daten an die Fabrik, wenn sie für die erste Erstellung des Objekts erforderlich sind.

Was benötige ich für diese Klasse? komplett zu machen, welche anderen Methoden sollte ich haben?

Bei vielen Fabriken handelt es sich nicht einmal um einzelne Klassen, sondern lediglich um Methoden zur Objekterzeugung. Sie könnten die Factory-Methode in eine andere Klasse falten, wenn Sie das Gefühl haben, dass sie nur einen parameterlosen Konstruktor aufrufen würde.

Sollte ich diese Klasse verwenden, um die das Produktobjekt aus der Domäne und dem Repository zu erstellen?

Das Repository dient zum Abrufen (in gewissem Sinne zum Erstellen) vorhandener Objekte, die Factory ist für die erstmalige Erstellung eines Objekts gedacht.

Anfänglich tun viele Fabriken nicht viel, außer einen Konstruktor aufzurufen. Sobald Sie jedoch mit dem Refactoring und/oder der Erstellung größerer Objekthierarchien beginnen, werden Fabriken immer wichtiger.

Erläuterung und Beispiel:

In dem Projekt, an dem ich arbeite, habe ich zum Beispiel eine Excel-Prozessor-Basisklasse und viele Unterklassen, die diese Basisklasse implementieren. Ich verwende die Fabrik, um die richtige Klasse zu finden, und rufe dann Methoden auf, ohne zu wissen, welche Unterklasse zurückgegeben wurde. (Hinweis: Ich habe einige Variablennamen geändert und eine Menge Code entkernt/geändert)

Basisklasse des Prozessors:

public abstract class ExcelProcessor
{
      public abstract Result Process(string ExcelFile);
}

Eine der Unterklassen von Processor:

public class CompanyAExcelProcessor : ExcelProcessor
{
     public override Result Process(string ExcelFile)
     {
      //cool stuff
     }
}

Fabrik:

 public static ExcelProcessor CreateExcelProcessor(int CompanyId, int CurrentUserId)
 {
      CompanyEnum company = GetCompanyEnum(CompanyId);
      switch (company)
      {
           case CompanyEnum.CompanyA:
                return new CompanyAExcelProcessor();
           case CompanyEnum.CompanyB:
                return new CompanyBExcelProcessor();
           case CompanyEnum.CompanyC:
                return new CompanyCExcelProcessor(CurrentUserId);
           //etc...
      }
 }

Verwendung:

ExcelProcessor processor = CreateExcelProcessor(12, 34);
processor.Process();

8voto

thinkbeforecoding Punkte 6520

Seien Sie vorsichtig, es gibt zwei Gründe für die Instanziierung eines neuen Objekts: Erstellen von es und Rehydrierung es aus der Datenbank.

Der erste Fall wird von der Fabrik bearbeitet. Sie können mehrere Methoden bereitstellen, um ein Objekt in der Fabrik zu erstellen. Factory-Methoden sollten gültige Objekte zurückgeben, so dass Sie diesen Methoden Parameter übergeben können, um die erforderlichen Informationen bereitzustellen.

Die Factory-Methode kann auch den zu instanziierenden Typ anhand von Parametern auswählen.

Sie sollten dies nicht mit der Rehydrierung aus der Datenbank kombinieren. Diese Art der Instanziierung sollte Werte aus der Datenreihe nehmen und das Objekt damit instanziieren. Ich nenne dies üblicherweise eine Datenersteller anstelle einer Werk .

Der Hauptunterschied besteht darin, dass die Factory ein Objekt mit einer neuen Identität instanziiert, während der Databuilder ein Objekt mit einer bereits vorhandenen Identität instanziiert.

3 Stimmen

Die Fabrik befindet sich normalerweise in der Domäne, während der Data Builder in der Persistenzinfrastruktur angesiedelt ist.

2voto

Chris Holmes Punkte 11104

Was in die Create-Methode Ihrer Fabrik gehört, ist alles, was notwendig ist, um ein brandneues Objekt in einen VALID-Zustand zu versetzen.

Für einige Objekte bedeutet das, dass Sie nichts anderes tun werden als dies:

public Product Create()
{
   return new Product();
}

Sie können jedoch Geschäftsregeln, Standardeinstellungen oder andere Anforderungen haben, die Sie bei der Erstellung eines Objekts durchsetzen wollen. In diesem Fall würden Sie diese Logik in dieser Methode unterbringen.

Und das ist ein Teil des Vorteils der Fabrik. Sie haben jetzt nur noch einen einzigen Ort, an dem sich diese spezielle Logik befindet, und nur noch einen Ort, an dem ein neues Objekt erstellt wird.

1voto

Tomas Pajonk Punkte 5042

Ich persönlich würde die Fabrik in einigen Fällen nutzen:

1) Etwas anderes regelt, welche Art von Objekten diese Fabrik zurückgibt (d.h. sie kann Objekte je nach Umständen zurückgeben. Zum Beispiel ein Stub-Objekt zurückgeben, wenn ich teste, eine tatsächliche Implementierung zurückgeben, wenn ich nicht bin (dies ist offensichtlich mehr von Inversion of Control / Dependency Injection Problem - aber wenn Sie nicht wollen, um Container zu Ihrem Projekt gerade noch hinzufügen)).

2) Ich habe recht komplexe Objekte mit Containern, Abhängigkeiten, anderen Beziehungen usw., die sorgfältig aufgebaut werden müssen, um die Erstellung von Null- oder sinnlosen Referenzen zu vermeiden. Wenn ich z. B. ein Schedule-Objekt habe, muss ich möglicherweise einige Felder für Start- und Enddatum festlegen. Wenn die Logik zum Abrufen und Ermitteln dieser Daten komplex genug ist, möchte ich möglicherweise nicht, dass die aufrufende Klasse davon erfährt, und rufe einfach die Standard-Fabrikmethode auf, mit der das Schedule-Objekt erstellt wurde.

Ich hoffe, das hilft.

0voto

Marc Gravell Punkte 970173

In dem obigen Beispiel ist mir die Unterscheidung zwischen Ihrer Fabrik und dem Repository nicht ganz klar. Ich frage mich, ob man nicht einfach CreateProduct als Methode zum Repository hinzufügen sollte und mit DI das Repository in den Code schieben sollte, der es benötigt? Wenn die Fabrik nicht bei irgendetwas, etc...

Oder wenn Sie es nur als global registriertes Repository verwenden wollen, vielleicht so etwas wie:

public static IFooRepository Default {get;private set;}
public static void SetRepository(IFooRepository repository) {
    Default = repository;
}

(meiner Meinung nach ist es klarer, die "Menge" in diesem Fall zu trennen, aber Sie müssen nicht zustimmen)

und lassen Sie die Anrufer var product = YourFactory.Default.CreateProduct(); usw.

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