본문 바로가기
IT/Design Pattern

Factory pattern

by how-are-you 2024. 5. 12.

제품을 생산하는 공장에서는 동일한 공정을 거치면서 내부 부품을 변경하거나 추가하여 여러 종류의 제품을 찍어냅니다. 이러한 상황에서 Factory 패턴은 매우 유용합니다. Factory 패턴은 동일한 틀을 가진 제품을 생성할 때, 클라이언트 코드가 직접 구체적인 클래스를 호출하는 대신, 인터페이스나 추상 클래스를 통해 객체 생성을 위한 메서드를 호출합니다. 이 메서드는 어떤 클래스의 인스턴스를 생성할 지 결정하고 해당 객체를 반환합니다. 이러한 설계 패턴을 사용하면 새로운 부품이나 기능이 추가되거나 변경될 때 손쉽게 제품을 확장하고 관리할 수 있습니다.

 

 

Factory pattern을 사용한 예시를 봅시다.


LifecycleManager의 Messenger 클래스는 DesignManager(DM)와 ServiceManager(SM)과 통신해야 하며, 각각의 메시지에 대한 ACK 이벤트를 생성해야 합니다. 이때, Messenger 클래스가 직접 DM과 SM에 의존하지 않고 통신을 하는 방법은 어떻게 해야 할까요?

2가지 기법이 추가됩니다.
- 인터페이스 추상화: Messenger 클래스는 DM과 SM 사이의 통신을 담당하는 인터페이스를 정의합니다. 이 인터페이스에는 각각의 메시지에 대한 처리 메서드가 포함됩니다.
- 팩토리 패턴: Messenger 클래스가 DM과 SM의 인스턴스를 직접 생성하는 것이 아니라, 팩토리 메서드나 추상 팩토리 패턴을 통해 생성된 인스턴스를 사용할 수 있습니다. 이를 통해 Messenger 클래스는 구체적인 클래스에 의존하지 않으면서도 필요한 인스턴스를 사용할 수 있습니다.

class diagram

 

하나의 MessageFactory 클래스를 생성하여 DesignManagerMessenger(DMM)와 ServiceManagerMessenger(SMM) 객체를 관리합니다. 이 MessageFactory는 vector를 사용하여 여러 객체를 보유합니다. DMM과 SMM은 둘 다 ExternalInterface 인터페이스를 따르며, 이는 두 클래스가 동일한 방식으로 다뤄질 수 있도록 합니다. MessageFactory는 받은 파라미터에 따라 DMM의 이벤트나 SMM의 이벤트를 반환하며, 이 메시지는 MessageHandler에서 처리됩니다.

 

이렇게 되면 새로운 DrawMessenger라는 새로운 곳과 통신을 할 때에도 MessageFactory의 벡터에 해당 객체를 추가해주기만 하면 됩니다. 이러면 확장에는 열려있고, 변화에는 닫혀있는 OCP를 만족하게 됩니다. 

위 과정을 C++로 구현해봅니다.

 

main문

int main() {
    std::shared_ptr<MessageHandler> messageHandler = std::make_shared<MessageHandler>();
    messageHandler->dispatchMessage("serviceManager", "Hello from Service Manager!");
    return 0;
}

 

main에서는 messageHandler객체를 생성하고 메시지를 받는 부분을 호출합니다. 

 

ExternalInterface와 그에 대한 구현체(SMM, DMM)

class ExternalInterface {
public:
    virtual bool isMyMessage(std::string processName) = 0;
    virtual std::shared_ptr<Event> makeEvent(std::string message) = 0;
};

class ServiceManagerMessenger : public ExternalInterface {
    bool isMyMessage(std::string processName) override {
        return (processName == NAME);
    }

    std::shared_ptr<Event> makeEvent(std::string message) override {
        std::shared_ptr<Event> event = std::make_shared<Event>(message);
        return event;
    }

    static std::string NAME;
};

std::string ServiceManagerMessenger::NAME = "serviceManager";

class DesignManagerMessenger : public ExternalInterface {
public:
    bool isMyMessage(std::string processName) override {
        return (processName == NAME);
    }

    std::shared_ptr<Event> makeEvent(std::string message) override {
        std::shared_ptr<Event> event = std::make_shared<Event>(message);
        return event;
    }

    static std::string NAME;
};

std::string DesignManagerMessenger::NAME = "designManager";

 

SMM과 DMM은 ExternalInterface를 상속하고, 각자의 메시지를 확인하고 event를 생성하는 함수를 가집니다.

 

MessageFactory

class MessageFactory {
public:
    MessageFactory() {
        std::shared_ptr<ServiceManagerMessenger> serviceManager = std::make_shared<ServiceManagerMessenger>();
        std::shared_ptr<DesignManagerMessenger> designManager = std::make_shared<DesignManagerMessenger>();
        messengers.push_back(serviceManager);
        messengers.push_back(designManager);
    }

    std::shared_ptr<Event> makeEvent(std::string processName, std::string message) {
        for (auto &messenger : messengers) {
            if (messenger->isMyMessage(processName)) {
                return messenger->makeEvent(message);
            }
        }
        return nullptr;
    }

private:
    std::vector<std::shared_ptr<ExternalInterface>> messengers;
};

MessageFactory는 processName과 message에 따라서 SMM의 이벤트면 SMM의 이벤트를 생성, DMM의 이벤트면 DMM의 이벤트를 생성합니다.

 

Event

class Event {
public:
    Event(std::string message) : message(message) {}
    std::string message;
};

 

MessageHandler

class MessageHandler {
public:
    MessageHandler() : MessageFactory(std::make_shared<MessageFactory>()) {}

    void dispatchMessage(std::string processName, std::string message) {
        EventHandler::injectpEvent(MessageFactory->makeEvent(processName, message));
    }

private:
    std::shared_ptr<MessageFactory> MessageFactory; 
};

MessageHandler 에서는 event를 eventHandler로 주입하고 eventHandler에서는 evnet 처리합니다. 

 

 

+ 더 생각해볼 점

여기서 dispatchMessage는 thread로 작성하여 message가 오면 interrupt를 걸어서 동작하게 하는 방식으로 변경하면 좋습니다.

 

 

'IT > Design Pattern' 카테고리의 다른 글

Singleton Pattern(feat. Logger)  (0) 2024.05.18
Observer Pattern  (0) 2024.05.15