Fabrikmuster. Wann werden Werksmethoden angewendet?

Antworten:

387

Ich denke gerne über Designmuster nach, wenn meine Klassen „Menschen“ sind, und die Muster sind die Art und Weise, wie die Menschen miteinander sprechen.

Für mich ist das Fabrikmuster also wie eine Personalagentur. Sie haben jemanden, der eine variable Anzahl von Arbeitern benötigt. Diese Person kennt möglicherweise einige Informationen, die sie für die von ihnen eingestellten Personen benötigt, aber das war's.

Wenn sie also einen neuen Mitarbeiter benötigen, rufen sie die Personalagentur an und sagen ihnen, was sie brauchen. Um tatsächlich jemanden einstellen zu können , müssen Sie eine Menge Dinge wissen - Vorteile, Überprüfung der Berechtigung usw. Aber die Person, die anstellt, muss nichts davon wissen - die Einstellungsagentur kümmert sich um all das.

Auf die gleiche Weise ermöglicht die Verwendung einer Factory dem Verbraucher, neue Objekte zu erstellen, ohne die Details zu kennen, wie sie erstellt wurden oder welche Abhängigkeiten sie haben - sie müssen nur die Informationen angeben, die sie tatsächlich möchten.

public interface IThingFactory
{
    Thing GetThing(string theString);
}

public class ThingFactory : IThingFactory
{
    public Thing GetThing(string theString)
    {
        return new Thing(theString, firstDependency, secondDependency);
    }
}

Jetzt kann der Verbraucher der ThingFactory eine Sache erhalten, ohne über die Abhängigkeiten der Sache Bescheid wissen zu müssen, mit Ausnahme der Zeichenfolgendaten, die vom Verbraucher stammen.

Kyoryu
quelle
17
Woher ruft die konkrete Implementierung von GetThing () die Werte von firstDependency und secondDependency ab?
Mikeyg36
88
Könnte mir jemand sagen, wie dies die Frage des OP beantwortet? Dies beschreibt lediglich, was 'Factory Pattern' ist, und fügt dann ein Beispiel für 'Factory Method' hinzu, das nur eines von drei 'Factory Patterns' ist. Mit anderen Worten, ich sehe nirgendwo einen Vergleich.
Forethinker
4
In der Frage von OP wird klar erwähnt within an object instead of a Factory class. Ich denke, er meinte das Szenario, in dem Sie den ctor privat machen und eine statische Methode verwenden, um die Klasse zu instanziieren (ein Objekt erstellen). ThingFactoryUm diesem Beispiel zu folgen, muss man zuerst die Klasse instanziieren , um ThingObjekte zu erhalten , was dies zu einem Factory classEffekt macht.
Atiyar
4
Entschuldigung, aber die Erklärung ist Mist, weil ein Konstruktor auch so geschrieben werden kann, dass die Abhängigkeiten ausgeblendet werden. Die wichtigsten Hintergrundinformationen, mit denen Sie die Informationen zur Abhängigkeitserstellung vom Abhängigkeitsmanagement trennen möchten, fehlen. Außerdem war die Frage ungefähr innerhalb derselben Klasse, die Antwort ist in keiner Weise damit verbunden.
Christian Hujer
8
OP fragte wann . Kyoryu antwortete wie . Obwohl der Stil der Antwort lobenswert ist, handelt es sich im Zusammenhang mit dieser Frage nur um Lärm.
8bitjunkie
96

Factory-Methoden sollten als Alternative zu Konstruktoren betrachtet werden - meistens, wenn Konstruktoren nicht ausdrucksstark genug sind, d. H.

class Foo{
  public Foo(bool withBar);
}

ist nicht so ausdrucksstark wie:

class Foo{
  public static Foo withBar();
  public static Foo withoutBar();
}

Factory-Klassen sind nützlich, wenn Sie einen komplizierten Prozess zum Erstellen des Objekts benötigen, wenn die Konstruktion eine Abhängigkeit benötigt, die Sie für die tatsächliche Klasse nicht benötigen, wenn Sie verschiedene Objekte usw. erstellen müssen.

Rasmus Faber
quelle
2
Wo ist die Factory-Klasse hier?
Koray Tugay
20
@KorayTugay: Es gibt keine Factory-Klasse, nur Factory-Methoden. Die Frage ist, wann Factory- Methoden anstelle einer Factory-Klasse verwendet werden sollen. Factory-Methoden sind jedoch eher eine Alternative zu Konstruktoren als eine Alternative zu Factory-Klassen. (Ich weiß nicht, warum die Top-Antwort so hoch bewertet wird, obwohl nur über Fabrikklassen gesprochen wird).
Rasmus Faber
5
Es ist zu beachten, dass sich statische Factory-Methoden vollständig vom Entwurfsmuster der Viererbande: Factory-Methode unterscheiden.
jaco0646
76

Eine Situation, in der ich persönlich separate Factory-Klassen für sinnvoll halte, besteht darin, dass das endgültige Objekt, das Sie erstellen möchten, von mehreren anderen Objekten abhängt. Beispiel: In PHP: Angenommen, Sie haben ein HouseObjekt, das wiederum ein Kitchenund ein LivingRoomObjekt enthält, und das LivingRoomObjekt enthält auch ein TVObjekt.

Die einfachste Methode, um dies zu erreichen, besteht darin, dass jedes Objekt seine untergeordneten Elemente mit seiner Konstruktionsmethode erstellt. Wenn die Eigenschaften jedoch relativ verschachtelt sind, werden Sie beim Housefehlgeschlagenen Erstellen wahrscheinlich einige Zeit damit verbringen, genau zu isolieren, was fehlschlägt.

Die Alternative besteht darin, Folgendes zu tun (Abhängigkeitsinjektion, wenn Sie den ausgefallenen Begriff mögen):

$TVObj = new TV($param1, $param2, $param3);
$LivingroomObj = new LivingRoom($TVObj, $param1, $param2);
$KitchenroomObj = new Kitchen($param1, $param2);
$HouseObj = new House($LivingroomObj, $KitchenroomObj);

Wenn der Prozess des Erstellens eines Housefehlschlägt, gibt es nur einen Ort, an dem Sie suchen müssen. Es ist jedoch alles andere als Housepraktisch, diesen Block jedes Mal verwenden zu müssen, wenn Sie einen neuen wünschen . Betreten Sie die Fabriken:

class HouseFactory {
    public function create() {
        $TVObj = new TV($param1, $param2, $param3);
        $LivingroomObj = new LivingRoom($TVObj, $param1, $param2);
        $KitchenroomObj = new Kitchen($param1, $param2);
        $HouseObj = new House($LivingroomObj, $KitchenroomObj);

        return $HouseObj;
    }
}

$houseFactory = new HouseFactory();
$HouseObj = $houseFactory->create();

Dank der Factory hier wird der Prozess des Erstellens eines a Houseabstrahiert (da Sie nicht jede einzelne Abhängigkeit erstellen und einrichten müssen, wenn Sie nur ein erstellen möchten House) und gleichzeitig zentralisiert, was die Wartung erleichtert. Es gibt andere Gründe, warum die Verwendung separater Fabriken von Vorteil sein kann (z. B. Testbarkeit), aber ich finde diesen speziellen Anwendungsfall, um am besten zu veranschaulichen, wie nützlich Factory-Klassen sein können.

Mahn
quelle
1
Wie würde jemand einen Unit-Test dazu machen? Ich dachte, die Verwendung des Schlüsselworts "new" in einer Klasse würde als schlechte Praxis angesehen, da es nicht einheitlich getestet werden kann. Oder soll eine Fabrik eine Ausnahme von dieser Regel sein?
AgmLauncher
1
@AgmLauncher Ich hatte die gleiche Frage auch, als ich mit Unit-Tests begann, check out: stackoverflow.com/questions/10128780/…
Mahn
1
Hab das nicht verstanden. Wie genau werden die Parameter zum Erstellen verschiedener Objekte an die HouseFactoryKlasse übergeben?
Atiyar
1
@ Mahn, hättest du am Ende nicht eine Menge Parameter?
Pacerier
1
@Pacerier , dass das etwas für Sie entscheiden , wie Modell, je nach Ihren Bedürfnissen, aber Sie müssen nicht immer passieren müssen , um alle Parameter an die createMethode. Wenn Sie Housebeispielsweise immer die gleiche Art von LivingRoomhaben, kann es sinnvoll sein, die Parameter in der Factory-Klasse fest zu codieren, anstatt sie als Argumente zu übergeben. Oder Sie möchten typeIhrer HouseFactory::createMethode ein Argument geben, wenn Sie einige Arten von LivingRooms haben und einen Schalter mit den für jeden Typ fest codierten Parametern haben.
Mahn
19

Es ist wichtig, die Idee hinter der Verwendung der Fabrik oder der Fabrikmethode klar zu unterscheiden. Beide sollen sich gegenseitig ausschließende Probleme bei der Objekterstellung ausschließen.

Lassen Sie uns die "Fabrikmethode" genau beschreiben:

Wenn Sie eine Bibliothek oder APIs entwickeln, die wiederum für die weitere Anwendungsentwicklung verwendet werden, ist die Factory-Methode eine der besten Auswahlmöglichkeiten für das Erstellungsmuster. Grund dahinter; Wir wissen, dass, wann ein Objekt mit den erforderlichen Funktionen erstellt werden soll, der Objekttyp jedoch unentschlossen bleibt oder ob dynamische Parameter übergeben werden .

Nun ist der Punkt, dass ungefähr dasselbe erreicht werden kann, indem das Factory-Muster selbst verwendet wird, aber ein großer Nachteil wird in das System eingeführt, wenn das Factory-Muster für das oben hervorgehobene Problem verwendet wird. Es ist, dass Ihre Logik, verschiedene Objekte (Unterklassenobjekte) zu erstellen, dies tut Seien Sie in Zukunft spezifisch für bestimmte Geschäftsbedingungen, wenn Sie die Funktionalität Ihrer Bibliothek für andere Plattformen erweitern müssen (Technisch gesehen müssen Sie weitere Unterklassen der Basisschnittstelle oder der abstrakten Klasse hinzufügen, damit Factory diese Objekte zusätzlich zu den vorhandenen auch zurückgibt basierend auf einigen dynamischen Parametern) dann jedes Mal, wenn Sie die Logik der Factory-Klasse ändern (erweitern) müssen, was kostspielig und aus konstruktiver Sicht nicht gut ist. Auf der anderen Seite, wenn "Fabrikmethode"

interface Deliverable 
{
    /*********/
}

abstract class DefaultProducer 
{

    public void taskToBeDone() 
    {   
        Deliverable deliverable = factoryMethodPattern();
    }
    protected abstract Deliverable factoryMethodPattern();
}

class SpecificDeliverable implements Deliverable 
{
 /***SPECIFIC TASK CAN BE WRITTEN HERE***/
}

class SpecificProducer extends DefaultProducer 
{
    protected Deliverable factoryMethodPattern() 
    {
        return new SpecificDeliverable();
    }
}

public class MasterApplicationProgram 
{
    public static void main(String arg[]) 
    {
        DefaultProducer defaultProducer = new SpecificProducer();
        defaultProducer.taskToBeDone();
    }
}
Prakash Chhipa
quelle
15

Sie sind auch nützlich, wenn Sie mehrere "Konstruktoren" mit demselben Parametertyp, aber unterschiedlichem Verhalten benötigen.

Rik
quelle
15

Es ist eine gute Idee, Factory-Methoden innerhalb des Objekts zu verwenden, wenn:

  1. Die Klasse des Objekts weiß nicht, welche Unterklassen genau erstellt werden müssen
  2. Die Klasse des Objekts ist so konzipiert, dass die von ihm erstellten Objekte von Unterklassen angegeben wurden
  3. Die Klasse von Object delegiert ihre Aufgaben an zusätzliche Unterklassen und weiß nicht, welche Klasse genau diese Aufgaben übernimmt

Es ist eine gute Idee, eine abstrakte Factory- Klasse zu verwenden, wenn:

  1. Ihr Objekt sollte nicht davon abhängen, wie seine inneren Objekte erstellt und gestaltet werden
  2. Eine Gruppe verknüpfter Objekte sollte zusammen verwendet werden, und Sie müssen diese Einschränkung erfüllen
  3. Das Objekt sollte von einer von mehreren möglichen Familien verknüpfter Objekte konfiguriert werden, die Teil Ihres übergeordneten Objekts sind
  4. Es ist erforderlich, untergeordnete Objekte freizugeben, die nur Schnittstellen, jedoch keine Implementierung anzeigen
Dzianis Yafimau
quelle
9

UML von

Geben Sie hier die Bildbeschreibung ein

Produkt: Definiert eine Schnittstelle der Objekte, die die Factory-Methode erstellt.

ConcreteProduct: Implementiert die Produktschnittstelle

Ersteller: Deklariert die Factory-Methode

ConcreateCreator: Implementiert die Factory-Methode, um eine Instanz eines ConcreteProduct zurückzugeben

Problemstellung: Erstellen Sie eine Factory of Games mithilfe von Factory-Methoden, die die Spieloberfläche definieren.

Code-Auszug:

import java.util.HashMap;


/* Product interface as per UML diagram */
interface Game{
    /* createGame is a complex method, which executes a sequence of game steps */
    public void createGame();
}

/* ConcreteProduct implementation as per UML diagram */
class Chess implements Game{
    public Chess(){

    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Chess game");
        System.out.println("Opponents:2");
        System.out.println("Define 64 blocks");
        System.out.println("Place 16 pieces for White opponent");
        System.out.println("Place 16 pieces for Black opponent");
        System.out.println("Start Chess game");
        System.out.println("---------------------------------------");
    }
}
class Checkers implements Game{
    public Checkers(){

    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Checkers game");
        System.out.println("Opponents:2 or 3 or 4 or 6");
        System.out.println("For each opponent, place 10 coins");
        System.out.println("Start Checkers game");
        System.out.println("---------------------------------------");
    }
}
class Ludo implements Game{
    public Ludo(){

    }
    public void createGame(){
        System.out.println("---------------------------------------");
        System.out.println("Create Ludo game");
        System.out.println("Opponents:2 or 3 or 4");
        System.out.println("For each opponent, place 4 coins");
        System.out.println("Create two dices with numbers from 1-6");
        System.out.println("Start Ludo game");
        System.out.println("---------------------------------------");
    }
}

/* Creator interface as per UML diagram */
interface IGameFactory {
    public Game getGame(String gameName);
}

/* ConcreteCreator implementation as per UML diagram */
class GameFactory implements IGameFactory {

     HashMap<String,Game> games = new HashMap<String,Game>();
    /*  
        Since Game Creation is complex process, we don't want to create game using new operator every time.
        Instead we create Game only once and store it in Factory. When client request a specific game, 
        Game object is returned from Factory instead of creating new Game on the fly, which is time consuming
    */

    public GameFactory(){

        games.put(Chess.class.getName(),new Chess());
        games.put(Checkers.class.getName(),new Checkers());
        games.put(Ludo.class.getName(),new Ludo());        
    }
    public Game getGame(String gameName){
        return games.get(gameName);
    }
}

public class NonStaticFactoryDemo{
    public static void main(String args[]){
        if ( args.length < 1){
            System.out.println("Usage: java FactoryDemo gameName");
            return;
        }

        GameFactory factory = new GameFactory();
        Game game = factory.getGame(args[0]);
        if ( game != null ){                    
            game.createGame();
            System.out.println("Game="+game.getClass().getName());
        }else{
            System.out.println(args[0]+  " Game does not exists in factory");
        }           
    }
}

Ausgabe:

java NonStaticFactoryDemo Chess
---------------------------------------
Create Chess game
Opponents:2
Define 64 blocks
Place 16 pieces for White opponent
Place 16 pieces for Black opponent
Start Chess game
---------------------------------------
Game=Chess

Dieses Beispiel zeigt eine FactoryKlasse durch Implementierung von a FactoryMethod.

  1. Gameist die Schnittstelle für alle Arten von Spielen. Es definiert komplexe Methoden:createGame()

  2. Chess, Ludo, Checkers Es gibt verschiedene Varianten von Spielen, die eine Implementierung ermöglichen createGame()

  3. public Game getGame(String gameName)ist FactoryMethodin der IGameFactoryKlasse

  4. GameFactoryErstellt verschiedene Arten von Spielen im Konstruktor vor. Es implementiert die IGameFactoryFactory-Methode.

  5. Der Spielname wird als Befehlszeilenargument an übergeben NotStaticFactoryDemo

  6. getGamein GameFactoryakzeptiert einen Spielnamen und gibt das entsprechende GameObjekt zurück.

Fabrik:

Erstellt Objekte, ohne die Instanziierungslogik dem Client zur Verfügung zu stellen.

FactoryMethod

Definieren Sie eine Schnittstelle zum Erstellen eines Objekts, lassen Sie jedoch die Unterklassen entscheiden, welche Klasse instanziiert werden soll. Mit der Factory-Methode kann eine Klasse die Instanziierung auf Unterklassen verschieben

Anwendungsfall:

Wann zu verwenden: Clientweiß nicht, welche konkreten Klassen zur Laufzeit erstellt werden müssen, sondern möchte nur eine Klasse erhalten, die den Job erledigt.

Ravindra Babu
quelle
Vielen Dank für Ihren Keynotes-Abschnitt, es ist prägnant für mich. Aber es ist unvorstellbar, dass "getArea () eine Factory-Methode in Form-Schnittstelle ist", da die Methode getArea NIEMALS eine Klasse instanziiert, sondern nur eine Berechnung durchführt Schnittstelle zum Erstellen eines Objekts, aber lassen Sie die Unterklassen entscheiden, welche Klasse instanziiert werden soll "bitte.
Reco
getArea()ist keine Factory - Methode überhaupt .
Cranio
1
Ich bin anderer Meinung - Experten validieren bitte und machen sich Notizen. 1. Client (oder Aufrufer) benötigt Objekt von Interesse ... sollte daher keine neue GameFactory () aufrufen müssen, sondern die Factory-Klasse sollte eine statische getInstance () haben. 2.Auch wenn ja, dann games.put (Chess.class.getName ( ), neues Schach ()); wird immer die gleiche Referenz von Chess zurückgeben [wenn als statisch implementiert] - wie geht man mit diesem Szenario am effektivsten um?
Arnab Dutta
Ich habe ein Beispiel für eine nicht statische Fabrik gegeben. Sie können es mit statischen Blöcken und Methoden implementieren, wenn Sie möchten. Zu Ihren Fragen: 1. Der Kunde wird Factory anrufen, um das Spiel zu erhalten. 2. Ich setze das Objekt einmal und alle Get geben dieselbe Instanz zurück - dieselbe Referenz von Chess wird für jedes get zurückgegeben
Ravindra babu
6

Es ist wirklich Geschmackssache. Factory-Klassen können nach Bedarf abstrahiert / verbunden werden, während Factory-Methoden leichter sind (und auch testbar sind, da sie keinen definierten Typ haben, aber einen bekannten Registrierungspunkt erfordern, der einem Service ähnelt Locator, aber zum Auffinden von Werksmethoden).

Brad Wilson
quelle
4

Factory-Klassen sind nützlich, wenn der von ihnen zurückgegebene Objekttyp einen privaten Konstruktor hat, wenn verschiedene Factory-Klassen unterschiedliche Eigenschaften für das zurückgebende Objekt festlegen oder wenn ein bestimmter Factory-Typ mit seinem zurückkehrenden Betontyp gekoppelt ist.

WCF verwendet ServiceHostFactory-Klassen, um ServiceHost-Objekte in verschiedenen Situationen abzurufen. Die Standard-ServiceHostFactory wird von IIS zum Abrufen von ServiceHost-Instanzen für SVC- Dateien verwendet. Eine WebScriptServiceHostFactory wird jedoch für Dienste verwendet, die Serialisierungen an JavaScript-Clients zurückgeben. ADO.NET Data Services verfügt über eine eigene spezielle DataServiceHostFactory und ASP.NET über eine ApplicationServicesHostFactory, da die Dienste über private Konstruktoren verfügen.

Wenn Sie nur eine Klasse haben, die die Factory verbraucht, können Sie einfach eine Factory-Methode innerhalb dieser Klasse verwenden.

Mark Cidade
quelle
2

Stellen Sie sich ein Szenario vor, in dem Sie eine Auftrags- und Kundenklasse entwerfen müssen. Der Einfachheit halber und den anfänglichen Anforderungen zufolge benötigen Sie für die Auftragsklasse keine Fabrik und füllen Ihre Anwendung mit vielen 'new Order ()' - Anweisungen. Die Dinge funktionieren gut.

Nun kommt eine neue Anforderung ins Spiel, dass das Bestellobjekt ohne Kundenzuordnung nicht instanziiert werden kann (neue Abhängigkeit). Jetzt haben Sie folgende Überlegungen.

1- Sie erstellen eine Konstruktorüberladung, die nur für neue Implementierungen funktioniert. (Inakzeptabel). 2- Sie ändern die Order () - Signaturen und ändern jeden Aufruf. (Keine gute Übung und echte Schmerzen).

Stattdessen Wenn Sie eine Factory für die Auftragsklasse erstellt haben, müssen Sie nur eine Codezeile ändern, und schon kann es losgehen. Ich empfehle die Factory-Klasse für fast jede aggregierte Assoziation. Hoffentlich hilft das.

Muhammad Awais
quelle
1

wenn Sie ein anderes Objekt in Bezug auf die Verwendung erstellen möchten. Es ist nützlich.

public class factoryMethodPattern {
      static String planName = "COMMERCIALPLAN";
      static int units = 3;
      public static void main(String args[]) {
          GetPlanFactory planFactory = new GetPlanFactory();
          Plan p = planFactory.getPlan(planName);
          System.out.print("Bill amount for " + planName + " of  " + units
                        + " units is: ");
          p.getRate();
          p.calculateBill(units);
      }
}

abstract class Plan {
      protected double rate;

      abstract void getRate();

      public void calculateBill(int units) {
            System.out.println(units * rate);
      }
}

class DomesticPlan extends Plan {
      // @override
      public void getRate() {
            rate = 3.50;
      }
}

class CommercialPlan extends Plan {
      // @override
      public void getRate() {
            rate = 7.50;
      }
}

class InstitutionalPlan extends Plan {
      // @override
      public void getRate() {
            rate = 5.50;
      }
}

class GetPlanFactory {

      // use getPlan method to get object of type Plan
      public Plan getPlan(String planType) {
            if (planType == null) {
                  return null;
            }
            if (planType.equalsIgnoreCase("DOMESTICPLAN")) {
                  return new DomesticPlan();
            } else if (planType.equalsIgnoreCase("COMMERCIALPLAN")) {
                  return new CommercialPlan();
            } else if (planType.equalsIgnoreCase("INSTITUTIONALPLAN")) {
                  return new InstitutionalPlan();
            }
            return null;
      }
}
Samet ÖZTOPRAK
quelle
1

Jede Klasse, die die Objekterstellung für das Objekt, mit dem sie arbeiten muss, auf ihre Unterklasse verschiebt, kann als Beispiel für ein Factory-Muster angesehen werden.

Ich habe dies in einer anderen Antwort unter https://stackoverflow.com/a/49110001/504133 ausführlich erwähnt

nits.kk
quelle
1

Ich denke, es hängt vom losen Kopplungsgrad ab, den Sie in Ihren Code einbringen möchten.

Die Fabrikmethode entkoppelt die Dinge sehr gut, aber die Fabrikklasse Nr.

Mit anderen Worten, es ist einfacher, Dinge zu ändern, wenn Sie die Factory-Methode verwenden, als wenn Sie eine einfache Factory (als Factory-Klasse bezeichnet) verwenden.

Schauen Sie sich dieses Beispiel an: https://connected2know.com/programming/java-factory-pattern/ . Stellen Sie sich nun vor, Sie möchten ein neues Tier mitbringen. In der Factory-Klasse müssen Sie die Factory ändern, aber in der Factory-Methode müssen Sie nur eine neue Unterklasse hinzufügen.

Tagus
quelle
0

Fabrikklassen sind schwerer, bieten aber gewisse Vorteile. In Fällen, in denen Sie Ihre Objekte aus mehreren Rohdatenquellen erstellen müssen, können Sie nur die Gebäudelogik (und möglicherweise die Aggregation der Daten) an einem Ort kapseln. Dort kann es abstrakt getestet werden, ohne sich um die Objektschnittstelle zu kümmern.

Ich habe festgestellt, dass dies ein nützliches Muster ist, insbesondere wenn ich ORM nicht ersetzen kann und unzureichend bin und viele Objekte aus DB-Tabellenverknüpfungen oder gespeicherten Prozeduren effizient instanziieren möchte.

jonfm
quelle
0

Ich vergleiche Fabriken mit dem Konzept der Bibliotheken. Beispielsweise können Sie eine Bibliothek zum Arbeiten mit Zahlen und eine andere zum Arbeiten mit Formen haben. Sie können die Funktionen dieser Bibliotheken in logisch benannten Verzeichnissen als Numbersoder speichern Shapes. Dies sind generische Typen, die bei Formen Ganzzahlen, Gleitkommazahlen, Dobuli, Longs oder Rechtecke, Kreise, Dreiecke und Pentagone umfassen können.

Der Factory Petter verwendet Polymorphismus, Abhängigkeitsinjektion und Inversion der Kontrolle.

Der angegebene Zweck der Fabrikmuster ist: Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

Nehmen wir also an, Sie erstellen ein Betriebssystem oder Framework und alle diskreten Komponenten.

Hier ist ein einfaches Beispiel für das Konzept des Factory-Musters in PHP. Ich bin vielleicht nicht zu 100% damit einverstanden, aber es soll als einfaches Beispiel dienen. Ich bin kein Experte.

class NumbersFactory {
    public static function makeNumber( $type, $number ) {
        $numObject = null;
        $number = null;

        switch( $type ) {
            case 'float':
                $numObject = new Float( $number );
                break;
            case 'integer':
                $numObject = new Integer( $number );
                break;
            case 'short':
                $numObject = new Short( $number );
                break;
            case 'double':
                $numObject = new Double( $number );
                break;
            case 'long':
                $numObject = new Long( $number );
                break;
            default:
                $numObject = new Integer( $number );
                break;
        }

        return $numObject;
    }
}

/* Numbers interface */
abstract class Number {
    protected $number;

    public function __construct( $number ) {
        $this->number = $number;
    }

    abstract public function add();
    abstract public function subtract();
    abstract public function multiply();
    abstract public function divide();
}
/* Float Implementation */
class Float extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Integer Implementation */
class Integer extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Short Implementation */
class Short extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Double Implementation */
class Double extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}
/* Long Implementation */
class Long extends Number {
    public function add() {
        // implementation goes here
    }

    public function subtract() {
        // implementation goes here
    }

    public function multiply() {
        // implementation goes here
    }

    public function divide() {
        // implementation goes here
    }
}

$number = NumbersFactory::makeNumber( 'float', 12.5 );
Robert Rocha
quelle
Ich verstehe, was hier passiert, aber ich verstehe nicht, worum es geht. Was gibt NumbersFactory::makeNumber( 'float', 12.5 );es mir zu sagen, new Float(12.5);wenn ich weiß, dass ich eine brauche Float? Das verstehe ich nicht über Fabriken ... worum geht es?
BadHorsie
Sie können verschiedene Implementierungen auswählen und sind nicht nur an eine gebunden. Eine Schnittstelle wird eingerichtet und alle Implementierungen müssen diese garantieren und einhalten.
Robert Rocha