2012-09-30 3 views
4

추상 팩토리 패턴을 구현하고 싶지만 싱글 톤이되고 싶습니다.싱글 톤 추상 팩토리 패턴

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

이 초록 공장 싱글 톤을 만드는 데 필요한 샘플 코드가 있습니까?

미리 감사드립니다.

답변

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

내가 어떻게했을까요.

+0

감사합니다. 이 특정 예에서 예. 그러나 매크로를 가능한 한 많이 사용하지 않고 가능한 한 객체 지향 원칙을 고수하고 싶습니다. – KodeWarrior

+0

그는 적어도 개념적으로는 매크로를 사용하지 않습니다. 그는 단순히 매크로 메커니즘을 사용하는 컴파일 플랫폼을 확인하는 중일뿐 일반적으로 매크로를 나쁜 선택으로 만드는 문제는 실제로는 없습니다. 컴파일러가 다른 방법으로 그런 수표를 제공하지 않는다는 것입니다. –

+0

sidenote : void를 반환하거나 일반적으로 코드 분기가 컴파일되지 않은 경우 컴파일러 오류를 발생시키지 않는 항목에 대해서는 마지막 "#else #error Missing implementation #endif"를 추가하여주의를 끌도록합니다. –

1

실제로 동적 추상 팩토리가 필요하면 런타임에 어떻게 든 설정해야합니다. 실제 싱글 톤을 설정하는 적절한 함수를 사용하여 원하는 팩토리를 선택하는 기능을 사용하면이 작업을 수행 할 수 있습니다. 실제 응용 프로그램에서는 factory (factory 팩토리 함수)에 대한 인스턴스를 가져 오는 함수를 등록 할 수있는 일종의 등록 함수가있을 것입니다. 아래의 예제에서는 컴파일 할 때 사용 가능한 팩토리를 알고있는 간단한 설정을 사용했습니다.

#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

이것은 단지 절대적으로 훌륭합니다! 감사. – KodeWarrior

6

나는 더 우아한 해결책을 내놓았다. 친절하게 당신의 생각을 알려주세요

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