Синглтон абстрактный фабричный образец

Я хотел бы реализовать шаблон Abstract Factory, но также хотел бы быть одиночкой.

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

Может ли кто-нибудь помочь мне с примером кода создания этого абстрактного фабричного синглтона?

Заранее спасибо.

4

Решение

Мне удалось придумать более элегантное решение (без проверки ошибок на данный момент). Пожалуйста, дайте мне знать ваши мысли

#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();
}
6

Другие решения

Если вам нужна действительно динамическая абстрактная фабрика, вам нужно как-то настроить ее во время выполнения. Вы можете сделать это, имея функцию выбора требуемой фабрики с подходящей функцией, которая просто устанавливает фактический синглтон. В реальном приложении у вас, вероятно, была бы какая-то функция регистрации, где вы можете регистрировать функции, получая экземпляр для фабрики (фабричные функции фабрики). В приведенном ниже примере я использовал простую настройку, в которой доступные фабрики известны во время компиляции.

#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 + "'");
}
}
1

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

Это то, как я бы это сделал.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector