Frage

In meiner Anwendung gibt es von 10 bis 20 Klassen, die einmal instanziiert [*]. Hier ein Beispiel:

class SomeOtherManager;

class SomeManagerClass {
public:
    SomeManagerClass(SomeOtherManager*);
    virtual void someMethod1();
    virtual void someMethod2();
};

Instanzen der Klassen sind in einem Objekt enthalten:

class TheManager {
public:
    virtual SomeManagerClass* someManagerClass() const;
    virtual SomeOtherManager* someOtherManager() const;
    /** More objects... up to 10-20 */
};

Zur Zeit TheManager verwendet den neuen Operator, um Objekte zu erstellen.

Meine Absicht ist es, Plugins zu ersetzen, zu verwenden, die SomeManagerClass (oder jede andere Klasse) Umsetzung mit einer anderen. Um sich die Umsetzung, 2 Schritte zu ersetzen benötigt:

  1. Definieren Sie eine Klasse DerivedSomeManagerClass, die SomeManagerClass [Plugin]
  2. erbt
  3. Erstellen Sie die neue Klasse (DerivedSomeManagerClass) anstelle des Standard (SomeManagerClass) [Anwendung]

Ich glaube, ich irgendeine Art von Objekt Fabrik benötigen, aber es sollte ziemlich einfach sein, da immer gibt es nur eine Art (die Standardimplementierung oder die Benutzer-Implementierung) zu erstellen.

Jede Idee, wie man eine einfache Fabrik zu entwerfen, wie ich gerade beschrieben? Betrachten Sie die Tatsache, dass es möglicherweise mehr Klassen in der Zukunft sein, so sollte es leicht sein, zu verlängern.

[*] ist mir egal, ob es mehr als einmal passiert.

Edit:. Bitte beachten Sie, dass es mehr als zwei Objekte, die in TheManager enthalten sind,

War es hilfreich?

Lösung

Ich denke, es gibt zwei verschiedene Probleme hier.

Ein Problem ist: wie funktioniert TheManager name die Klasse, es hat zu schaffen? Es muss eine Art Zeiger auf „eine Möglichkeit, die Klasse zu erstellen“ halten. Mögliche Lösungen sind:

  • einen separaten Zeiger für jede Art von Klasse zu halten, mit einem Weg, es zu setzen, aber du schon gesagt, dass du das nicht gefällt, wie es das DRY-Prinzip
  • verletzt
  • eine Art von Tisch zu halten, wo der Schlüssel eine Enumeration oder ein String ist; in diesem Fall ist der Setter eine einzelne Funktion mit Parametern (natürlich, wenn der Schlüssel eine Enumeration ist einen Vektor anstelle einer Karte verwenden)

Das andere Problem ist: Was ist dieser „Weg, um eine Klasse zu erstellen“? Leider können wir nicht speichern Zeiger auf Konstrukteure direkt, aber wir können:

  • schaffen, wie andere haben darauf hingewiesen, eine Fabrik für jede Klasse
  • fügen Sie einfach eine statische „erstellen“ -Funktion für jede Klasse; wenn sie eine einheitliche Signatur halten, können Sie einfach ihre Zeiger auf Funktionen nutzen

Vorlagen können bei der Vermeidung unnötiger Code-Duplizierung in beiden Fällen helfen.

Andere Tipps

Unter der Annahme, eine Klasse (plugin1), die von SomeManagerClass erbt, müssen Sie eine Klassenhierarchie Ihre Typen erstellen:

class factory
{
public:
    virtual SomeManagerClass* create() = 0;
};

class plugin1_factory : public factory
{
public:
    SomeManagerClass* create() { return new plugin1(); }
};

Dann können Sie diese Fabriken zu einem std :: map zuordnen, wo sie in Strings gebunden sind

std::map<string, factory*>  factory_map;
...
factory_map["plugin1"] = new plugin1_factory();

Schließlich Ihre TheManager brauchen nur den Namen des Plug-in kennen (als String) und können ein Objekt vom Typ SomeManagerClass mit nur einer Codezeile zurück:

SomeManagerClass* obj = factory_map[plugin_name]->create();

Bearbeiten : Wenn Sie nicht für jedes Plugin einer Plugin-Factory-Klasse haben mögen, können Sie das vorherige Muster mit diesem ändern könnten:

template <class plugin_type>
class plugin_factory : public factory
{
public:
   SomeManagerClass* create() { return new plugin_type(); }
};

factory_map["plugin1"] = new plugin_factory<plugin1>();

Ich denke, das ist eine viel bessere Lösung. Darüber hinaus ist die ‚plugin_factory‘ Klasse selbst auf die ‚factory_map‘ hinzufügen könnte, wenn Sie costructor die Zeichenfolge übergeben.

Ich habe in einer anderen SO Frage zu C ++ Fabriken beantwortet. Bitte finden Sie unter es wenn eine flexible Fabrik von Interesse ist. Ich versuche, einen alten Weg von ET zu beschreiben ++ Makros zu verwenden, die gut für mich gearbeitet hat.

ET ++ war ein Projekt zum Hafen alt MacApp zu C ++ und X11. In dem Bestreben, es Eric Gamma usw. begonnen, darüber nachzudenken, Design Patterns

Ich würde eine „Basis“ Fabrik erstellen, die für die Erstellung von allen grundlegenden Managern virtuelle Methoden haben, und lassen Sie den „Meta-Manager“ (TheManager in Ihrer Frage) als Konstruktor Parameter einen Zeiger auf die Basis Fabrik nehmen.

Ich gehe davon aus, dass die „Fabrik“ die Instanzen von CXYZWManager anpassen kann von ihnen durch Ableiten, aber alternativ kann der Konstrukteur CXYZWManager könnte unterschiedliche Argumente in der „custom“ Fabrik nehmen.

Ein längeres Codebeispiel, das "CSomeManager" und "CDerivedFromSomeManager" ausgibt:

#include <iostream>
//--------------------------------------------------------------------------------
class CSomeManager
  {
  public:
    virtual const char * ShoutOut() { return "CSomeManager";}
  };

//--------------------------------------------------------------------------------
class COtherManager
  {
  };

//--------------------------------------------------------------------------------
class TheManagerFactory
  {
  public:
    // Non-static, non-const to allow polymorphism-abuse
    virtual CSomeManager   *CreateSomeManager() { return new CSomeManager(); }
    virtual COtherManager  *CreateOtherManager() { return new COtherManager(); }
  };

//--------------------------------------------------------------------------------
class CDerivedFromSomeManager : public CSomeManager
  {
  public:
    virtual const char * ShoutOut() { return "CDerivedFromSomeManager";}
  };

//--------------------------------------------------------------------------------
class TheCustomManagerFactory : public TheManagerFactory
  {
  public:
    virtual CDerivedFromSomeManager        *CreateSomeManager() { return new CDerivedFromSomeManager(); }

  };

//--------------------------------------------------------------------------------
class CMetaManager
  {
  public:
    CMetaManager(TheManagerFactory *ip_factory)
      : mp_some_manager(ip_factory->CreateSomeManager()),
        mp_other_manager(ip_factory->CreateOtherManager())
      {}

    CSomeManager  *GetSomeManager()  { return mp_some_manager; }
    COtherManager *GetOtherManager() { return mp_other_manager; }

  private:
    CSomeManager  *mp_some_manager;
    COtherManager *mp_other_manager;
  };

//--------------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
  {
  TheManagerFactory standard_factory;
  TheCustomManagerFactory custom_factory;

  CMetaManager meta_manager_1(&standard_factory);
  CMetaManager meta_manager_2(&custom_factory);

  std::cout << meta_manager_1.GetSomeManager()->ShoutOut() << "\n";
  std::cout << meta_manager_2.GetSomeManager()->ShoutOut() << "\n";
  return 0;
  }

Hier ist die Lösung, die ich dachte, es ist nicht die beste, aber vielleicht wird es helfen, bessere Lösungen zu denken:

Für jede Klasse gibt es wäre ein Schöpfer Klasse sein:

class SomeManagerClassCreator {
public:
    virtual SomeManagerClass* create(SomeOtherManager* someOtherManager) { 
        return new SomeManagerClass(someOtherManager); 
    }
};

Dann werden die Schöpfer in einer Klasse entnommen werden:

class SomeManagerClassCreator;
class SomeOtherManagerCreator;

class TheCreator {
public:
    void setSomeManagerClassCreator(SomeManagerClassCreator*);
    SomeManagerClassCreator* someManagerClassCreator() const;

    void setSomeOtherManagerCreator(SomeOtherManagerCreator*);
    SomeOtherManagerCreator* someOtherManagerCreator() const;
private:
    SomeManagerClassCreator* m_someManagerClassCreator;
    SomeOtherManagerCreator* m_someOtherManagerCreator;
};

Und TheManager werden mit TheCreator für die interne Erstellung erstellt werden:

class TheManager {
public:
    TheManager(TheCreator*);
    /* Rest of code from above */
};

Das Problem bei dieser Lösung ist, dass es trocken verletzt - für jede Klasse Schöpfer würde ich Setter / Getter in TheCreator schreiben

.

Dies scheint, wie es viel einfacher, mit Funktion Templat zu einer Abstrakte Fabrik im Gegensatz würde

class ManagerFactory
{
public:
    template <typename T> static BaseManager * getManager() { return new T();}
};

BaseManager * manager1 = ManagerFactory::template getManager<DerivedManager1>();

Wenn Sie sie über einen String erhalten möchten, können Sie eine Standard-Karte von Strings erstellen Zeiger funktionieren. Hier ist eine Implementierung, die funktioniert:

#include <map>
#include <string>

class BaseManager
{
public:
    virtual void doSomething() = 0;
};

class DerivedManager1 : public BaseManager
{
public:
    virtual void doSomething() {};
};

class DerivedManager2 : public BaseManager
{
public:
    virtual void doSomething() {};
};

class ManagerFactory
{
public:
    typedef BaseManager * (*GetFunction)();
    typedef std::map<std::wstring, GetFunction> ManagerFunctionMap;
private:
    static ManagerFunctionMap _managers;

public:
    template <typename T> static BaseManager * getManager() { return new T();}
    template <typename T> static void registerManager(const std::wstring& name)
    {
        _managers[name] = ManagerFactory::template getManager<T>;
    }
    static BaseManager * getManagerByName(const std::wstring& name)
    {
        if(_managers.count(name))
        {
            return _managers[name]();
        }
        return NULL;
    }
};
// the static map needs to be initialized outside the class
ManagerFactory::ManagerFunctionMap ManagerFactory::_managers;


int _tmain(int argc, _TCHAR* argv[])
{
    // you can get with the templated function
    BaseManager * manager1 = ManagerFactory::template getManager<DerivedManager1>();
    manager1->doSomething();
    // or by registering with a string
    ManagerFactory::template registerManager<DerivedManager1>(L"Derived1");
    ManagerFactory::template registerManager<DerivedManager2>(L"Derived2");
    // and getting them
    BaseManager * manager2 = ManagerFactory::getManagerByName(L"Derived2");
    manager2->doSomething();
    BaseManager * manager3 = ManagerFactory::getManagerByName(L"Derived1");
    manager3->doSomething();
    return 0;
}

Bearbeiten : die anderen Antworten Beim Lesen wurde mir klar, dass dies zu Dave Van den Eynde der FactorySystem Lösung sehr ähnlich ist, aber ich bin ein Funktions-Template Zeiger statt Instanziieren Templat-Factory-Klassen verwenden. Ich glaube, meine Lösung ein wenig leichter ist. Durch statische Funktionen, das einzige Objekt, das instanziiert wird die Karte selbst. Wenn Sie die Fabrik, um andere Funktionen auszuführen (DestroyManager, etc.), ich glaube, seine Lösung mehr erweiterbar ist.

Sie können ein Objekt Fabrik mit statischen Methoden implementieren, die eine Instanz eines Managers-Klasse zurück. In der Fabrik können Sie eine Methode für den Standardtyp-Manager und ein Verfahren für jede Art von Manager erstellen, die Sie ein Argument geben, die den Typ des Managers-Klasse (etwa mit einem Enum). Diese letzte Methode sollte eine Schnittstelle zurückgeben statt einer Klasse.

Edit:. Ich werde versuchen, einige Codes zu geben, aber daran, dass meine C ++ Zeiten sind schon eine Weile zurück, und ich mache nur Java und einige scripting einstweilen

class Manager { // aka Interface
    public: virtual void someMethod() = 0;
};

class Manager1 : public Manager {
    void someMethod() { return null; }
};

class Manager2 : public Manager {
    void someMethod() { return null; }
};

enum ManagerTypes {
    Manager1, Manager2
};

class ManagerFactory {
    public static Manager* createManager(ManagerTypes type) {
        Manager* result = null;
        switch (type) {
        case Manager1:
             result = new Manager1();
             break;
        case Manager2:
             result = new Manager2();
             break;
        default:
             // Do whatever error logging you want
             break;
        }
        return result;
     }
 };

Nun sollten Sie in der Lage sein, um die Fabrik zu rufen über (wenn Sie sind in der Lage, das Codebeispiel Arbeit zu machen):

Manager* manager = ManagerFactory.createManager(ManagerTypes.Manager1);

würde ich Vorlagen wie diese verwendet, da ich nicht den Punkt der Fabriken Klassen sehen kann:

class SomeOtherManager;

class SomeManagerClass {
public:
    SomeManagerClass(SomeOtherManager*);
    virtual void someMethod1();
    virtual void someMethod2();
};


class TheBaseManager {
public:
      // 
};

template <class ManagerClassOne, class ManagerClassOther> 
class SpecialManager : public TheBaseManager {
    public:
        virtual ManagerClassOne* someManagerClass() const;
        virtual ManagerClassOther* someOtherManager() const;
};

TheBaseManager* ourManager = new SpecialManager<SomeManagerClass,SomeOtherManager>;

Sie sollten einen Blick auf das Tutorial nehmen an http://downloads.sourceforge.net/papafactory/PapaFactory20080622.pdf?use_mirror= fastbull

Es enthält ein großes Tutorial eine Zusammenfassung Fabrik in C ++ auf die Implementierung und den Quellcode, der mit ihm kommt auch sehr robust

Chris

Mh Ich verstehe nicht hundertprozentig, und ich bin nicht wirklich in Fabrik Sachen aus Büchern und Artikeln.


Wenn alle Ihre Manager haben eine ähnliche Schnittstelle, die Sie von einer Basisklasse ableiten könnte, und benutzen Sie diese Basisklasse in Ihrem Programm. Je nachdem, wo die Entscheidung, die gemacht werden kann Klasse erstellt wird, müssen Sie eine Kennung für die Erstellung verwenden (wie oben angegeben) oder die Entscheidung handhaben, welche Manager intern zu instanziiert.


Eine andere Möglichkeit wäre, sie umzusetzen „Politik“ wie durch Vorlagen. So dass Sie ManagerClass :: create () gibt eine bestimmte SomeOtherManagerWhatever Instanz. Dies würde die Entscheidung legen, die Manager in dem Code zu machen, die Ihre Manager verwendet -. Maye ist dies nicht beabsichtigt

oder auf diese Weise:


template<class MemoryManagment>
class MyAwesomeClass
{
    MemoryManagment m_memoryManager;
};

(oder so ähnlich) Mit diesem Konstrukt können Sie ganz einfach andere Manager verwenden, indem nur die Instantiierung MyAwesomeClass ändern.


Auch eine Klasse für diesen Zweck könnte ein wenig übertrieben sein. In Ihrem Fall tun würde, eine Fabrik-Funktion, denke ich. Nun, es ist mehr eine Frage des persönlichen Geschmacks.

Wenn Sie auf der Unterstützung von Plugins planen, die dynamisch verknüpft sind, wird Ihr Programm braucht ein stabiles ABI (Application Binary Interface) zur Verfügung zu stellen, das bedeutet, dass Sie nicht C ++ als Haupt-Schnittstelle als C ++ keinen Standard ABI haben verwenden können.

Wenn Sie Plugins wollen eine Schnittstelle Sie selbst definieren zu implementieren, müssen Sie die Header-Datei der Schnittstelle zur Verfügung stellen müssen Programmierer Plugin und zu standardisieren, auf eine sehr einfache C-Schnittstelle, um das Objekt zu erstellen und löschen.

Sie können eine dynamische Bibliothek, die Sie zu „neu“ die Plugin-Klasse als Service-Leistung ermöglicht. Deshalb ist man auf einer C-Schnittstelle zu standardisieren, um benötigt um das Objekt zu erstellen. das Objekt C ++ verwendet, ist dann möglich, solange keine Ihrer Argumente möglicherweise inkompatible Typen verwenden, wie STL-Containern. Sie werden nicht durch eine andere Bibliothek zurück einen Vektor nutzen können, weil Sie nicht sicherstellen können, dass ihre STL-Implementierung die gleiche wie bei Ihnen.

Manager.h

class Manager
{
public:
  virtual void doSomething() = 0;
  virtual int doSomethingElse() = 0;
}

extern "C" {
Manager* newManager();
void deleteManager(Manager*);
}

PluginManager.h

#include "Manager.h"

class PluginManager : public Manager
{
public:
  PluginManager();
  virtual ~PluginManager();

public:
  virtual void doSomething();
  virtual int doSomethingElse();
}

PluginManager.cpp

#include "PluginManager.h"

Manager* newManager()
{
  return new PluginManager();
}
void deleteManager(Manager* pManager)
{
  delete pManager;
}

PluginManager::PluginManager()
{
  // ...
}

PluginManager::~PluginManager()
{
  // ...
}

void PluginManager::doSomething()
{
  // ...
}

int PluginManager::doSomethingElse()
{
  // ...
}

Sie knapp über TheManager sprechen. Es sieht aus wie Sie, dass steuern möchten, welche Klasse verwendet wird? oder vielleicht haben Sie sie an die Kette versuchen zusammen?

Es klingt wie Sie eine abstrakte Basisklasse und einen Zeiger auf die aktuell verwendete Klasse benötigen. Wenn Sie an die Kette möchten, können Sie es sowohl in der abstrakten Klasse und themanager Klasse tun. Wenn abstrakte Klasse, ein Mitglied in der nächsten Klasse in der Kette hinzufügen, wenn themanager es dann sortieren, um Sie, die in einer Liste zu verwenden. Sie werden einen Weg brauchen, um Klassen hinzuzufügen, so dass Sie eine addme benötigen () in themanager. Es klingt wie Sie wissen, was Sie tun so w / e Sie recht entscheiden sollten. Eine Liste mit einer addme func ist meine Empfehlung und wenn Sie nur 1 aktive Klasse wollen dann eine Funktion in TheManagern es entscheidet, wäre gut.

Diese vielleicht schwerer als Sie brauchen, aber es klingt wie Sie einen Rahmenarbeitsklasse zu machen versuchen, die Plug-in unterstützt.

Ich würde es lösen sich in 3 Abschnitte.

1) Die Framework-Klasse würde die Plugins besitzen. Diese Klasse ist verantwortlich für die Veröffentlichung von Schnittstellen durch die Plug-in geliefert.

2) Eine PlugIn-Klasse würde die componets besitzen, die die Arbeit tun. Diese Klasse ist verantwortlich für die exportierten Schnittstellen Registrierung und Bindung der importierten Schnittstellen zu den Komponenten.

3) Der dritte Abschnitt sind die componets die Lieferanten und Konsumenten von den Schnittstellen.

Um die Dinge erweiterbar zu machen, Dinge Aufstehen und Laufen könnte in Stufen auflöste werden.

  1. Erstellen Sie alles.
  2. Draht alles auf.
  3. Starten Sie alles.

Dinge brechen.

  1. Stop alles.
  2. Zerstört alles.
class IFrameWork {
public:
    virtual ~IFrameWork() {}
    virtual void RegisterInterface( const char*, void* ) = 0;
    virtual void* GetInterface( const char* name ) = 0;
};

class IPlugIn {
public:
    virtual ~IPlugIn() {}
    virtual void BindInterfaces( IFrameWork* frameWork ) {};
    virtual void Start() {};
    virtual void Stop() {};
};

struct SamplePlugin :public IPlugIn {
    ILogger* logger;

    Component1 component1;
    WebServer  webServer;

public:
    SamplePlugin( IFrameWork* frameWork ) 
        :logger( (ILogger*)frameWork->GetInterface( "ILogger" ) ),  //assumes the 'System' plugin exposes this
        component1(),
        webServer( component1 )
    {
        logger->Log( "MyPlugin Ctor()" );

        frameWork->RegisterInterface( "ICustomerManager", dynamic_cast( &component1 ) ); 
        frameWork->RegisterInterface( "IVendorManager", dynamic_cast( &component1 ) ); 
        frameWork->RegisterInterface( "IAccountingManager", dynamic_cast( &webServer ) ); 
    }

    virtual void BindInterfaces( IFrameWork* frameWork ) {
        logger->Log( "MyPlugin BindInterfaces()" );

        IProductManager* productManager( static_cast( frameWork->GetInterface( "IProductManager" ) ) );
        IShippingManager* shippingManager( static_cast( frameWork->GetInterface( "IShippingManager" ) ) );

        component1.BindInterfaces( logger, productManager );
        webServer.BindInterfaces( logger, productManager, shippingManager );
    }

    virtual void Start() {
        logger->Log( "MyPlugin Start()" );

        webServer.Start();
    }

    virtual void Stop() {
        logger->Log( "MyPlugin Stop()" );

        webServer.Stop();
    }
};

class FrameWork :public IFrameWork {
    vector plugIns;
    map interfaces;
public:
    virtual void RegisterInterface( const char* name, void* itfc ) {
        interfaces[ name ] = itfc;
    }
    virtual void* GetInterface( const char* name )  {
        return interfaces[ name ];
    }

    FrameWork() {
        //Only interfaces in 'SystemPlugin' can be used by all methods of the other plugins
        plugIns.push_back( new SystemPlugin( this ) );

        plugIns.push_back( new SamplePlugin( this ) ); 
        //add other plugIns here

        for_each( plugIns.begin(), plugIns.end(), bind2nd( mem_fun( &IPlugIn::BindInterfaces ), this ) );
        for_each( plugIns.begin(), plugIns.end(), mem_fun( &IPlugIn::Start ) );
    }

    ~FrameWork() {
        for_each( plugIns.rbegin(), plugIns.rend(), mem_fun( &IPlugIn::Stop ) );
        for_each( plugIns.rbegin(), plugIns.rend(), Delete() );
    }
};

Hier ist eine minimal-Fabrik-Muster-Implementierung, die ich mit in etwa 15 Minuten kam. Wir verwenden einen ähnlichen, die erweiterte Basisklassen verwendet.

#include "stdafx.h"
#include <map>
#include <string>

class BaseClass
{
public:
    virtual ~BaseClass() { }
    virtual void Test() = 0;
};

class DerivedClass1 : public BaseClass 
{ 
public:
    virtual void Test() { } // You can put a breakpoint here to test.
};

class DerivedClass2 : public BaseClass 
{ 
public:
    virtual void Test() { } // You can put a breakpoint here to test.
};

class IFactory
{
public:
    virtual BaseClass* CreateNew() const = 0;
};

template <typename T>
class Factory : public IFactory
{
public:
    T* CreateNew() const { return new T(); }
};

class FactorySystem
{
private:
    typedef std::map<std::wstring, IFactory*> FactoryMap;
    FactoryMap m_factories;

public:
    ~FactorySystem()
    {
        FactoryMap::const_iterator map_item = m_factories.begin();
        for (; map_item != m_factories.end(); ++map_item) delete map_item->second;
        m_factories.clear();
    }

    template <typename T>
    void AddFactory(const std::wstring& name)
    {
        delete m_factories[name]; // Delete previous one, if it exists.
        m_factories[name] = new Factory<T>();
    }

    BaseClass* CreateNew(const std::wstring& name) const
    {
        FactoryMap::const_iterator found = m_factories.find(name);
        if (found != m_factories.end())
            return found->second->CreateNew();
        else
            return NULL; // or throw an exception, depending on how you want to handle it.
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    FactorySystem system;
    system.AddFactory<DerivedClass1>(L"derived1");
    system.AddFactory<DerivedClass2>(L"derived2");

    BaseClass* b1 = system.CreateNew(L"derived1");
    b1->Test();
    delete b1;
    BaseClass* b2 = system.CreateNew(L"derived2");
    b2->Test();
    delete b2;

    return 0;
}

einfach kopieren und eine anfängliche Win32-Konsole app in VS2005 / 2008 bekleben. Ich mag etwas hinweisen:

  • Sie brauchen nicht ein Betonwerk für jede Klasse zu erstellen. Eine Vorlage wird für Sie das tun.
  • Ich mag die ganze Fabrik Muster in seiner eigenen Klasse zu platzieren, so dass Sie brauchen, um über das Erstellen von Fabrikobjekten keine Sorge und Löschen von ihnen. Sie gibt einfach Ihre Klassen registrieren, eine Factory-Klasse wird durch den Compiler und ein Factory-Objekt wird durch das Muster erstellt erstellt. Am Ende seiner Lebensdauer, werden alle Fabriken sauber zerstört. Ich mag diese Form der Verkapselung, da es keine Verwirrung darüber, wer die Lebensdauer der Fabriken regelt.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top