2012-09-30 2 views
4

Je voudrais mettre en œuvre un modèle d'usine abstraite mais aimerais aussi être un singleton.Modèle d'usine abstrait Singleton

class WindowFactory { 
protected: 
    virtual Scrollbar* createScrollbar() = 0; 
}; 

class MacWindowFactory: public WindowFactory { 
    virtual Scrollbar* createScrollbar() { 
     //return a instance 
    } 
    ; 
}; 

class LinuxWindowFactory: public WindowFactory { 
    virtual ScrollBar* createScrollbar() { 
     //return a instance 
    } 
    ; 
}; 

Est-ce que quelqu'un peut m'aider avec un exemple de code pour faire ce Abstract Factory Singleton?

Merci d'avance.

Répondre

0
namespace WindowFactory { 
     Scrollbar* createScrollbar() { 
     #ifdef TARGET_OS_MAC 
     ... 
     #elif __linux__ 
     ... 
     #endif 
     } 
}; 

C'est comme ça que je l'aurais fait.

+0

Merci. Dans cet exemple spécifique oui. Mais je voudrais éviter autant que possible l'utilisation de macros et m'en tenir le plus possible à des principes orientés objet. – KodeWarrior

+0

Il n'utilise pas de macros, du moins pas conceptuellement. Il vérifie simplement la plate-forme de compilation, qui utilise le mécanisme de la macro, mais ne présente aucun des problèmes qui rendent généralement les macros un mauvais choix. C'est juste qu'aucun compilateur n'offre de telles vérifications d'une autre manière. –

+0

Note: pour les choses qui retournent void, ou qui ne provoquent généralement pas d'erreur de compilation lorsqu'aucune branche de code n'est compilée, j'ajoute aussi un "#else #error Missing implementation #endif" final pour s'assurer qu'il est remarqué. –

1

Si vous avez besoin d'une fabrique abstraite réellement dynamique, vous devez la configurer en cours d'exécution. Vous pouvez le faire en ayant une fonction sélectionnant l'usine désirée avec une fonction appropriée qui établit juste le singleton réel. Dans une application réelle, vous auriez probablement une sorte de fonction d'enregistrement où vous pouvez enregistrer des fonctions pour obtenir une instance pour l'usine (fonctions d'usine). Dans l'exemple ci-dessous, j'ai utilisé une configuration simple où les usines disponibles sont connues au moment de la compilation.

#include <memory> 
#include <stdexcept> 
#include <string> 

class Scrollbar; 

class WindowFactory { 
public: 
    static void setFactory(std::string const&); 
    static Scrollbar* createScrollbar(); 
    virtual ~WindowFactory() {} 

private: 
    virtual Scrollbar* doCreateScrollbar() = 0; 
}; 

class MacWindowFactory 
    : public WindowFactory { 
    friend void WindowFactory::setFactory(std::string const&); 
    virtual Scrollbar* doCreateScrollbar() { 
     return 0; 
    } 
}; 

class LinuxWindowFactory 
    : public WindowFactory { 
    friend void WindowFactory::setFactory(std::string const&); 
    virtual Scrollbar* doCreateScrollbar() { 
     return 0; 
    } 
}; 

// in WindowFactory.cpp 

static std::auto_ptr<WindowFactory>& getPointer() 
{ 
    static std::auto_ptr<WindowFactory> pointer; 
    return pointer; 
} 

Scrollbar* WindowFactory::createScrollbar() 
{ 
    return getPointer().get() 
     ? getPointer()->doCreateScrollbar() 
     : throw std::runtime_error("WindowFactory not set"); 
} 

void WindowFactory::setFactory(std::string const& what) 
{ 
    if (what == "Mac") { 
     getPointer() = std::auto_ptr<WindowFactory>(new MacWindowFactory()); 
    } 
    else if (what == "Linux") { 
     getPointer() = std::auto_ptr<WindowFactory>(new LinuxWindowFactory()); 
    } 
    else { 
     throw std::runtime_error("unknown factory: '" + what + "'"); 
    } 
} 
+0

C'est absolument génial! Merci. – KodeWarrior

6

j'ai réussi à trouver une solution plus élégante (Pas de contrôle d'erreur à partir de maintenant). Veuillez me faire savoir vos pensées

#include<iostream> 
#include<map> 

class AbstractFactory 
{ 
private: 
    typedef std::map< std::string, AbstractFactory* > ClientMap; 
    static ClientMap s_clientMap; 
public: 
    void virtual createScrollbar() = 0; 
    void virtual createWindow() = 0; 
    static AbstractFactory* createInstance(std::string client); 
protected: 
    void Register(std::string, AbstractFactory*); 
}; 

AbstractFactory::ClientMap AbstractFactory::s_clientMap; 

class LinuxFactory: public AbstractFactory 
{ 
public: 
    void createScrollbar() 
    { 
     std::cout<<"Scrollbar for Linux"<<std::endl; 
    } 

    void createWindow() 
    { 
     std::cout<<"WIndow for Linux"<<std::endl; 
    } 
private: 
    LinuxFactory() 
    { 
     Register("Linux", this); 
    } 
    LinuxFactory(const LinuxFactory&); 
    static LinuxFactory s_LinuxFactory; 

}; 
LinuxFactory LinuxFactory::s_LinuxFactory; 

class MacFactory: public AbstractFactory 
{ 
public: 
    void createScrollbar() 
    { 
     std::cout<<"Scrollbar for Mac"<<std::endl; 
    } 

    void createWindow() 
    { 
     std::cout<<"WIndow for Mac"<<std::endl; 
    } 

private: 
    MacFactory() 
    { 
     Register("Mac", this); 
    } 
    MacFactory(const MacFactory&); 
    static MacFactory s_MacFactory; 
}; 
MacFactory MacFactory::s_MacFactory; 

void AbstractFactory::Register(std::string clientName, AbstractFactory* factory) 
{ 
    s_clientMap.insert(ClientMap::value_type(clientName, factory)); 

} 
AbstractFactory* AbstractFactory::createInstance(std::string client) 
{ 
return s_clientMap.find(client)->second; 

} 

int main() 
{ 
AbstractFactory *factory = AbstractFactory::createInstance("Linux"); 
factory->createScrollbar(); 
factory->createWindow(); 
} 
Questions connexes