C++ Factory Method 패턴

추상 Creator가 객체 생성 인터페이스를 정의하고, 서브클래스가 구체적인 객체를 생성하는 Factory Method 패턴입니다. 알림(Notification) 발송 시스템을 예시로 구현합니다.

Gist
#include <iostream>
#include <memory>
#include <string>
#include <vector>

// ─────────────────────────────────────────────
// Product 인터페이스: 모든 알림 채널의 공통 계약
// ─────────────────────────────────────────────
class Notification {
public:
    virtual ~Notification() = default;
    virtual void send(const std::string& recipient,
                      const std::string& message) const = 0;
    virtual std::string channelName() const = 0;
};

// ─────────────────────────────────────────────
// ConcreteProduct: 이메일 알림
// ─────────────────────────────────────────────
class EmailNotification final : public Notification {
public:
    void send(const std::string& recipient,
              const std::string& message) const override {
        std::cout << "[EMAIL] → " << recipient
                  << " : " << message << "\n";
    }
    std::string channelName() const override { return "Email"; }
};

// ─────────────────────────────────────────────
// ConcreteProduct: SMS 알림
// ─────────────────────────────────────────────
class SmsNotification final : public Notification {
public:
    void send(const std::string& recipient,
              const std::string& message) const override {
        std::cout << "[SMS]   → " << recipient
                  << " : " << message << "\n";
    }
    std::string channelName() const override { return "SMS"; }
};

// ─────────────────────────────────────────────
// ConcreteProduct: 슬랙 알림
// ─────────────────────────────────────────────
class SlackNotification final : public Notification {
public:
    void send(const std::string& recipient,
              const std::string& message) const override {
        std::cout << "[SLACK] → #" << recipient
                  << " : " << message << "\n";
    }
    std::string channelName() const override { return "Slack"; }
};

// ─────────────────────────────────────────────
// Creator 인터페이스: 팩토리 메서드를 선언
// 공통 비즈니스 로직은 여기에 구현
// ─────────────────────────────────────────────
class NotificationSender {
public:
    virtual ~NotificationSender() = default;

    // 팩토리 메서드 — 서브클래스가 반드시 구현
    virtual std::unique_ptr<Notification> createNotification() const = 0;

    // 공통 로직: 채널 정보 출력 후 발송
    void notify(const std::string& recipient,
                const std::string& message) const {
        auto notif = createNotification();
        std::cout << "[" << notif->channelName() << " 채널 사용] ";
        notif->send(recipient, message);
    }

    // 벌크 발송: 여러 수신자에게 동일 메시지 전달
    void broadcastAll(const std::vector<std::string>& recipients,
                      const std::string& message) const {
        for (const auto& r : recipients) {
            notify(r, message);
        }
    }
};

// ─────────────────────────────────────────────
// ConcreteCreator: 각 채널별 발송자 구현
// ─────────────────────────────────────────────
class EmailSender final : public NotificationSender {
public:
    std::unique_ptr<Notification> createNotification() const override {
        return std::make_unique<EmailNotification>();
    }
};

class SmsSender final : public NotificationSender {
public:
    std::unique_ptr<Notification> createNotification() const override {
        return std::make_unique<SmsNotification>();
    }
};

class SlackSender final : public NotificationSender {
public:
    std::unique_ptr<Notification> createNotification() const override {
        return std::make_unique<SlackNotification>();
    }
};

// ─────────────────────────────────────────────
// 사용 예시
// ─────────────────────────────────────────────
int main() {
    // 각 Creator를 다형적으로 사용
    std::vector<std::unique_ptr<NotificationSender>> senders;
    senders.push_back(std::make_unique<EmailSender>());
    senders.push_back(std::make_unique<SmsSender>());
    senders.push_back(std::make_unique<SlackSender>());

    // 단일 발송
    for (const auto& sender : senders) {
        sender->notify("admin@example.com", "서버 배포 완료");
    }

    std::cout << "\n--- 브로드캐스트 ---\n";

    // 벌크 발송: Creator 인터페이스만 알면 됨 (구체 타입 불필요)
    std::vector<std::string> recipients = {"user1", "user2", "user3"};
    senders[2]->broadcastAll(recipients, "시스템 점검 예정 안내");

    return 0;
}