سؤال

في التطبيق ، هناك 10-20 الفئات التي يتم إنشاء مثيل مرة واحدة[*].هنا مثال:

class SomeOtherManager;

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

حالات من الطبقات الموجودة في كائن واحد:

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

حاليا TheManager يستخدم جديد المشغل من أجل خلق الكائنات.

نيتي هي أن تكون قادرة على استبدال باستخدام الإضافات ، SomeManagerClass (أو أي فئة أخرى) التنفيذ مع واحد آخر.من أجل استبدال التنفيذ ، 2 الخطوات اللازمة:

  1. تحديد فئة DerivedSomeManagerClass الذي يرث SomeManagerClass [المساعد]
  2. إنشاء فئة جديدة (DerivedSomeManagerClass) بدلا من الافتراضي (SomeManagerClass) [تطبيق]

أعتقد أنني في حاجة إلى نوع من كائن المصنع ، ولكن يجب أن تكون بسيطة إلى حد ما لأن هناك دائما نوع واحد فقط لخلق (الافتراضي التنفيذ أو التنفيذ المستخدم).

أي فكرة عن كيفية تصميم مصنع بسيط مثل أنا فقط وصفه ؟ النظر في حقيقة أنه قد يكون هناك المزيد من الدورات في المستقبل ، لذلك ينبغي أن يكون من السهل على تمديد.

[*] لا يهمني إذا حدث ذلك أكثر من مرة.

تحرير: يرجى ملاحظة أن هناك أكثر من اثنين من الكائنات الموجودة في TheManager.

هل كانت مفيدة؟

المحلول

أعتقد أن هناك اثنين منفصلة المشاكل هنا.

مشكلة واحدة هي:كيف TheManager اسم الفئة التي يجب أن تخلق ؟ فإنه يجب الحفاظ على نوع من مؤشر إلى "وسيلة لخلق الطبقة".الحلول الممكنة:

  • يحتفظ مؤشر لكل نوع من الصف ، مع طريقة وضعه لكنك قلت أنك لا تحب هذا كما أنه ينتهك مبدأ الجافة
  • الحفاظ على نوع من الجدول حيث المفتاح هو التعداد أو سلسلة ؛ في هذه الحالة اضع هو وظيفة واحدة مع المعلمات (طبعا إذا كان المفتاح هو التعداد يمكنك استخدام ناقلات بدلا من خريطة)

المشكلة الأخرى هي:ما هو هذا "الطريق إلى إنشاء فئة"?للأسف لا يمكننا تخزين مؤشرات إلى منشئات مباشرة ، ولكن يمكننا:

  • إنشاء كما أشار آخرون ، مصنع لكل فئة
  • فقط إضافة ثابت "خلق" وظيفة لكل فئة ؛ إذا أنها تبقى ثابتة التوقيع يمكنك فقط استخدام مؤشرات وظائف

قوالب يمكن أن تساعد في تجنب لا لزوم لها رمز الازدواجية في كلتا الحالتين.

نصائح أخرى

على افتراض فئة (plugin1) الذي يرث من SomeManagerClass تحتاج الهرمي فئة لبناء أنواع:

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

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

ثم يمكنك تعيين تلك المصانع إلى std::الخريطة ، حيث أنها ترتبط السلاسل

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

أخيرا الخاص بك TheManager فقط يحتاج إلى معرفة اسم البرنامج المساعد (as string) و يمكن إرجاع كائن من نوع SomeManagerClass مع سطر واحد فقط من التعليمات البرمجية:

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

تحرير:إذا كنت لا ترغب في أن يكون واحدا المساعد مصنع فئة لكل المساعد, يمكنك تعديل النمط السابق مع هذا:

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

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

أعتقد أن هذا حل أفضل بكثير.وعلاوة على ذلك 'plugin_factory' الفئة يمكن أن تضيف نفسها إلى 'factory_map' إذا كنت تمر costructor السلسلة.

لقد أجبت في آخر لذلك السؤال عن C++ المصانع.يرجى الاطلاع هناك إذا مرنة مصنع من الفائدة.أنا في محاولة لوصف الطريقة القديمة من ET++ استخدام وحدات الماكرو التي عملت كبيرة بالنسبة لي.

وآخرون++ كان مشروع الميناء القديم MacApp إلى C++ و X11.في محاولة منه اريك غاما وما إلى ذلك بدأت التفكير أنماط التصميم

أود إنشاء "قاعدة" المصنع يحتوي الظاهري طرق إنشاء الأساسية للمديرين ، والسماح "الفوقية" مدير (TheManager في سؤالك) تأخذ مؤشر إلى قاعدة مصنع كمعلمة منشئ.

أنا على افتراض أن "المصنع" يمكن تخصيص حالات CXYZWManager قبل المستمدة منها, ولكن بدلا من ذلك منشئ CXYZWManager يمكن أن تأخذ حجج مختلفة في "العرف" المصنع.

طويلة المثال التعليمات البرمجية التي النواتج "CSomeManager" و "CDerivedFromSomeManager":

#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;
  }

هنا هو الحل فكرت انها ليست أفضل واحد ولكن ربما أنها سوف تساعد على التفكير في حلول أفضل:

لكل فئة لن يكون هناك خالق الدرجة:

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

ثم المبدعين سيتم جمعها في فئة واحدة:

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;
};

و TheManager سيتم إنشاؤها مع TheCreator الداخلية الخلق:

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

المشكلة مع هذا الحل هو أنه ينتهك الجاف لكل فئة الخالق أود أن أكتب اضع/حاصل في TheCreator.

هذا يبدو وكأنه سيكون أبسط كثيرا مع وظيفة النموذجيه بدلا مجردة نمط مصنع

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

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

إذا كنت ترغب في الحصول عليها عبر سلسلة ، يمكنك إنشاء خريطة موحدة من سلاسل مؤشرات الدالة.هنا هو تنفيذ تلك الأعمال:

#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;
}

تحرير:في قراءة إجابات أخرى أدركت أن هذه هي مشابهة جدا ديف Van den Eynde هو FactorySystem الحل, ولكن أنا باستخدام وظيفة قالب المؤشر بدلا من إنشاء قالب مصنع الطبقات.أعتقد أن الحل هو قليلا أكثر خفيفة الوزن.ويرجع ذلك إلى وظائف ثابتة ، الكائن الوحيد الذي يحصل مثيل هو الخريطة نفسها.إذا كنت في حاجة إلى مصنع لأداء وظائف أخرى (DestroyManager ، الخ) ، أعتقد أن الحل هو أكثر الموسعة.

يمكنك تنفيذ مصنع كائن مع أساليب ثابتة أن عودة مثيل مدير الدرجة.في المصنع يمكنك إنشاء طريقة الافتراضي نوع من مدير الطريقة لأي نوع من مدير والتي تعطي حجة تمثل نوع من مدير الدرجة (يقول مع التعداد).هذا الأسلوب الأخير يجب أن تعود واجهة بدلا من فئة.

تحرير:سأحاول إعطاء بعض التعليمات البرمجية ، لكن العقل بلدي C++ مرة فترة طويلة و أنا أقوم فقط جافا و بعض البرمجة في الوقت الراهن.

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;
     }
 };

الآن يجب أن تكون قادرا على الاتصال المصنع عن طريق (إذا كنت قادرا على جعل رمز عينة العمل):

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

وأود أن استخدام قوالب مثل هذا كما لا أستطيع أن أرى وجهة المصانع فصول:

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>;

يجب أن نلقي نظرة على البرنامج التعليمي في http://downloads.sourceforge.net/papafactory/PapaFactory20080622.pdf?use_mirror=fastbull

أنه يحتوي على مجموعة كبيرة التعليمي على تنفيذ مصنع مجردة في C++ و شفرة المصدر التي تأتي مع أنه هو أيضا قوية جدا

كريس

Mh أنا لا أفهم مئة في المئة, و أنا لست حقا في مصنع الاشياء من الكتب والمقالات.


إذا كان كل ما تبذلونه من مديري حصة واجهة مماثلة يمكن أن تستمد من الفئة الأساسية, واستخدام هذه الفئة الأساسية في البرنامج.اعتمادا على حيث القرار الذي سيتم إنشاء الفئة سوف يكون عليك استخدام معرف الخلق (كما ذكر أعلاه) أو التعامل مع قرار مدير مثيل داخليا.


طريقة أخرى سيكون لتنفيذ ذلك "السياسة" مثل باستخدام القوالب.بحيث يمكنك ManagerClass::إنشاء() بإرجاع محددة SomeOtherManagerWhatever سبيل المثال.وهذا من شأنه وضع قرار مدير جعل في التعليمات البرمجية التي تستخدم Manager - مايي ليس هذا هو المقصود.

أو أن الطريقة:


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

(أو شيء من هذا القبيل) مع هذا البرنامج يمكنك بسهولة استخدام المديرين الآخرين فقط من خلال تغيير إنشاء مثيل من MyAwesomeClass.


أيضا فئة لهذا الغرض قد يكون قليلا أكثر من اللازم.في حالة مصنع وظيفة لا أعتقد.انه أكثر مسألة تفضيل شخصي.

إذا كنت تخطط على دعم الإضافات التي ترتبط بشكل حيوي, البرنامج الخاص بك سوف تحتاج إلى توفير مستقرة أبي (واجهة تطبيق ثنائية) ، وهذا يعني أنه لا يمكنك استخدام C++ الرئيسي الخاص بك واجهة مثل C++ لا يوجد لديه معيار أبي.

إذا كنت تريد الإضافات لتنفيذ واجهة تعرف نفسك, سيكون لديك لتوفير رأس الملف من واجهة البرنامج المساعد مبرمج على توحيد بسيط جدا ج واجهة من أجل إنشاء و حذف الكائن.

لا يمكن توفير مكتبة ديناميكية من شأنها أن تسمح لك ل "الجديد" البرنامج المساعد من الطبقة كما هو.هذا هو السبب في أنك بحاجة لتوحيد على ج واجهة من أجل إنشاء الكائن.باستخدام C++ كائن ثم ممكن طالما أن أيا من الحجج استخدام وربما تتعارض أنواع, مثل المحكمة الخاصة بلبنان الحاويات.سوف لا تكون قادرة على استخدام ناقلات عاد من مكتبة أخرى ، لأنه لا يمكن التأكد من أن المحكمة الخاصة بلبنان التنفيذ هو نفس لك.

مدير.ح

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

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

PluginManager.ح

#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()
{
  // ...
}

أنت لم تتحدث عن TheManager.يبدو أنك تريد أن تحكم في أي صف هو ؟ أو ربما كنت في محاولة سلسلة لهم معا ؟

يبدو أنك بحاجة إلى الفئة الأساسية مجردة و مؤشر المستخدمة حاليا في الدرجة.إذا كنت ترغب في سلسلة يمكنك أن تفعل ذلك في كل من خلاصة الدرجة themanager الدرجة.إذا خلاصة الدرجة ، إضافة عضو إلى الصف التالي في السلسلة ، إذا themanager ثم نوع في التي في القائمة.سوف تحتاج إلى طريقة لإضافة فصول لذا عليك addMe() في themanager.يبدو أنك تعرف ما تفعل الخاص بك حتى w/e اخترت أن يكون على حق.قائمة مع addMe ظائفها هو توصيتي و إذا كنت تريد فقط 1 النشط الصف ثم وظيفة في TheManager تقرر أنه سيكون جيد.

هذا ربما أثقل عليك ولكن يبدو أنك تحاول جعل إطار عمل الطبقة التي تدعم الإضافات.

أود أن تقسيمها إلى 3 أقسام.

1) إطار الفئة الخاصة الإضافات.هذه الدرجة هو مسؤول عن النشر واجهات المقدمة من الإضافات.

2) البرنامج المساعد الفئة الخاصة للcomponets أن القيام بهذا العمل.هذه الدرجة هو مسؤول عن تسجيل تصدير واجهات وملزمة المستوردة واجهات المكونات.

3) القسم الثالث ، للcomponets هم الموردين والمستهلكين من الواجهات.

لجعل الأمور للمد ، في تدبير الأمور قد اندلعت في مراحل.

  1. خلق كل شيء.
  2. سلك كل شيء.
  3. بداية كل شيء.

كسر الأشياء.

  1. توقف كل شيء.
  2. تدمير كل شيء.
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() );
    }
};

هنا الحد الأدنى من نمط مصنع التنفيذ التي خطرت في حوالي 15 دقيقة.نحن نستخدم مجموعة مماثلة واحد يستخدم أكثر تقدما قاعدة الطبقات.

#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;
}

فقط نسخ و لصق على أولي وحدة تحكم Win32 التطبيق في VS2005/2008.أود أن أشير إلى شيء:

  • أنت لا تحتاج إلى إنشاء مصنع الخرسانة لكل فئة.قالب سوف نفعل ذلك لك.
  • أود أن المكان بأكمله نمط مصنع في فئتها الخاصة ، حتى أن كنت لا داعي للقلق حول إنشاء مصنع الكائنات وحذفها.يمكنك ببساطة تسجيل الفصول الدراسية, مصنع يحصل على الدرجة التي تم إنشاؤها بواسطة برنامج التحويل البرمجي و مصنع كائن يحصل إنشاؤه من قبل نمط.في نهاية العمر, جميع المصانع نظيفة تدميرها.أنا أحب هذا النوع من التغليف ، كما أن هناك أي التباس حول من يحكم مدى الحياة من المصانع.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top