C++ Abstract Factory 패턴
서로 연관된 객체 집합(제품군)을 일관성 있게 생성하는 Abstract Factory 패턴입니다. 다크/라이트 테마 UI 위젯 팩토리를 예시로 구현합니다.
#include <iostream>
#include <memory>
#include <string>
// ─────────────────────────────────────────────
// Abstract Product A: 버튼 인터페이스
// ─────────────────────────────────────────────
class Button {
public:
virtual ~Button() = default;
virtual void render() const = 0;
virtual void onClick() const = 0;
};
// ─────────────────────────────────────────────
// Abstract Product B: 체크박스 인터페이스
// ─────────────────────────────────────────────
class Checkbox {
public:
virtual ~Checkbox() = default;
virtual void render() const = 0;
virtual void toggle() = 0;
virtual bool isChecked() const = 0;
};
// ─────────────────────────────────────────────
// Abstract Product C: 입력 필드 인터페이스
// ─────────────────────────────────────────────
class InputField {
public:
virtual ~InputField() = default;
virtual void render() const = 0;
virtual void setValue(const std::string& val) = 0;
virtual std::string getValue() const = 0;
};
// ─────────────────────────────────────────────
// ConcreteProduct (Light 테마): 버튼, 체크박스, 입력 필드
// ─────────────────────────────────────────────
class LightButton final : public Button {
public:
void render() const override { std::cout << " [Light 버튼] 흰 배경 / 검은 글씨\n"; }
void onClick() const override { std::cout << " [Light 버튼] 클릭 이벤트 발생\n"; }
};
class LightCheckbox final : public Checkbox {
public:
void render() const override { std::cout << " [Light 체크박스] □ 상태: " << (checked_ ? "✓" : "✗") << "\n"; }
void toggle() override { checked_ = !checked_; }
bool isChecked() const override { return checked_; }
private:
bool checked_{false};
};
class LightInputField final : public InputField {
public:
void render() const override { std::cout << " [Light 입력창] 값: \"" << value_ << "\"\n"; }
void setValue(const std::string& v) override { value_ = v; }
std::string getValue() const override { return value_; }
private:
std::string value_;
};
// ─────────────────────────────────────────────
// ConcreteProduct (Dark 테마): 버튼, 체크박스, 입력 필드
// ─────────────────────────────────────────────
class DarkButton final : public Button {
public:
void render() const override { std::cout << " [Dark 버튼] 검은 배경 / 흰 글씨\n"; }
void onClick() const override { std::cout << " [Dark 버튼] 클릭 이벤트 발생\n"; }
};
class DarkCheckbox final : public Checkbox {
public:
void render() const override { std::cout << " [Dark 체크박스] ■ 상태: " << (checked_ ? "✓" : "✗") << "\n"; }
void toggle() override { checked_ = !checked_; }
bool isChecked() const override { return checked_; }
private:
bool checked_{false};
};
class DarkInputField final : public InputField {
public:
void render() const override { std::cout << " [Dark 입력창] 값: \"" << value_ << "\"\n"; }
void setValue(const std::string& v) override { value_ = v; }
std::string getValue() const override { return value_; }
private:
std::string value_;
};
// ─────────────────────────────────────────────
// Abstract Factory: 제품군 생성 인터페이스
// ─────────────────────────────────────────────
class UIFactory {
public:
virtual ~UIFactory() = default;
virtual std::unique_ptr<Button> createButton() const = 0;
virtual std::unique_ptr<Checkbox> createCheckbox() const = 0;
virtual std::unique_ptr<InputField> createInputField() const = 0;
virtual std::string themeName() const = 0;
};
// ─────────────────────────────────────────────
// ConcreteFactory: Light / Dark 테마 팩토리
// ─────────────────────────────────────────────
class LightThemeFactory final : public UIFactory {
public:
std::unique_ptr<Button> createButton() const override { return std::make_unique<LightButton>(); }
std::unique_ptr<Checkbox> createCheckbox() const override { return std::make_unique<LightCheckbox>(); }
std::unique_ptr<InputField> createInputField() const override { return std::make_unique<LightInputField>(); }
std::string themeName() const override { return "Light"; }
};
class DarkThemeFactory final : public UIFactory {
public:
std::unique_ptr<Button> createButton() const override { return std::make_unique<DarkButton>(); }
std::unique_ptr<Checkbox> createCheckbox() const override { return std::make_unique<DarkCheckbox>(); }
std::unique_ptr<InputField> createInputField() const override { return std::make_unique<DarkInputField>(); }
std::string themeName() const override { return "Dark"; }
};
// ─────────────────────────────────────────────
// Client: 팩토리 인터페이스만 의존 — 구체 타입 무관
// ─────────────────────────────────────────────
void renderLoginForm(const UIFactory& factory) {
std::cout << "\n=== [" << factory.themeName() << " 테마] 로그인 폼 렌더링 ===\n";
auto emailInput = factory.createInputField();
auto passwordInput = factory.createInputField();
auto rememberMe = factory.createCheckbox();
auto loginBtn = factory.createButton();
emailInput->setValue("user@example.com");
passwordInput->setValue("••••••••");
rememberMe->toggle(); // 체크 상태로 변경
emailInput->render();
passwordInput->render();
rememberMe->render();
loginBtn->render();
loginBtn->onClick();
}
// ─────────────────────────────────────────────
// 사용 예시
// ─────────────────────────────────────────────
int main() {
// 런타임에 테마 선택 가능 — 클라이언트 코드 변경 불필요
auto lightFactory = std::make_unique<LightThemeFactory>();
auto darkFactory = std::make_unique<DarkThemeFactory>();
renderLoginForm(*lightFactory);
renderLoginForm(*darkFactory);
return 0;
}