24.2. 프로그램언어 C++에서의 팩토리 패턴

프로그램언어 C++의 팩토리 패턴 개념

팩토리 패턴은 객체지향 프로그래밍에서 사용되는 디자인 패턴 중 하나로, 객체의 생성을 담당하는 팩토리 클래스를 통해 객체를 생성하는 방식을 말합니다. 이 패턴은 객체 생성을 캡슐화하여 클라이언트가 직접 객체를 생성하는 것을 방지하고, 유연성을 높여줍니다.

팩토리 패턴은 주로 다음과 같은 상황에서 사용됩니다.

  • 객체 생성 과정이 복잡하거나 다양한 조건에 따라 다른 객체를 생성해야 할 때
  • 객체 생성 로직을 클라이언트로부터 분리하여 의존성을 낮추고 유지보수성을 높일 때

이제 C++에서의 팩토리 패턴을 예제 코드를 통해 살펴보겠습니다.


#include <iostream>
#include <memory>

// Product 인터페이스
class Product {
public:
    virtual void operation() = 0;
};

// ConcreteProduct 클래스
class ConcreteProduct : public Product {
public:
    void operation() override {
        std::cout << "ConcreteProduct operation\n";
    }
};

// 팩토리 클래스
class Factory {
public:
    std::unique_ptr<Product> createProduct() {
        return std::make_unique<ConcreteProduct>();
    }
};

int main() {
    Factory factory;
    std::unique_ptr<Product> product = factory.createProduct();
    product->operation();

    return 0;
}

위 예제 코드에서는 Product 인터페이스를 정의하고 ConcreteProduct 클래스가 이를 구현합니다. Factory 클래스는 createProduct 메서드를 통해 ConcreteProduct 객체를 생성하고 반환합니다. 클라이언트는 Factory를 통해 객체를 생성하고 사용할 수 있습니다.

프로그램언어 C++에서의 팩토리 패턴 적용법

프로그램언어 C++에서의 팩토리 패턴은 객체지향 디자인 패턴 중 하나로, 객체 생성을 캡슐화하여 클라이언트가 직접 객체를 생성하는 것이 아니라 팩토리 클래스를 통해 객체를 생성하도록 하는 패턴입니다.

팩토리 패턴을 적용하기 위해서는 먼저 추상 클래스나 인터페이스를 정의하고, 이를 상속받는 여러 하위 클래스를 만들어야 합니다. 그리고 이러한 하위 클래스들을 생성하는 팩토리 클래스를 구현하여 객체 생성을 담당하게 됩니다.

아래는 C++에서의 팩토리 패턴을 예제 코드로 보여드리겠습니다.


#include <iostream>
#include <memory>

// 추상 클래스
class Product {
public:
    virtual void use() = 0;
};

// 구체적인 클래스들
class ConcreteProductA : public Product {
public:
    void use() override {
        std::cout << "Using Product A" << std::endl;
    }
};

class ConcreteProductB : public Product {
public:
    void use() override {
        std::cout << "Using Product B" << std::endl;
    }
};

// 팩토리 클래스
class Factory {
public:
    std::unique_ptr<Product> createProduct(const std::string& type) {
        if (type == "A") {
            return std::make_unique<ConcreteProductA>();
        } else if (type == "B") {
            return std::make_unique<ConcreteProductB>();
        } else {
            return nullptr;
        }
    }
};

int main() {
    Factory factory;
    
    std::unique_ptr<Product> productA = factory.createProduct("A");
    productA->use();
    
    std::unique_ptr<Product> productB = factory.createProduct("B");
    productB->use();
    
    return 0;
}

프로그램언어 C++의 팩토리 패턴 사용 사례

팩토리 패턴은 객체 생성을 캡슐화하여 클라이언트가 직접 객체를 생성하는 것을 방지하고, 객체 생성 로직을 분리하여 유연성을 제공하는 디자인 패턴입니다.

프로그램언어 C++에서 팩토리 패턴을 사용하는 사례 중 하나는 다양한 유형의 도형을 생성하는 예시입니다. 도형을 나타내는 기본 클래스인 Shape을 정의하고, 이를 상속받는 여러 도형 클래스(Circle, Square, Triangle 등)를 만듭니다. 팩토리 클래스를 통해 클라이언트는 원하는 도형을 생성할 수 있습니다.

아래는 C++에서 도형 팩토리 패턴을 구현한 예제 코드입니다.


#include <iostream>
#include <memory>

// Shape 클래스 정의
class Shape {
public:
    virtual void draw() = 0;
};

// Circle 클래스 정의
class Circle : public Shape {
public:
    void draw() override {
        std::cout << "Circle drawn" << std::endl;
    }
};

// Square 클래스 정의
class Square : public Shape {
public:
    void draw() override {
        std::cout << "Square drawn" << std::endl;
    }
};

// Triangle 클래스 정의
class Triangle : public Shape {
public:
    void draw() override {
        std::cout << "Triangle drawn" << std::endl;
    }
};

// 팩토리 클래스 정의
class ShapeFactory {
public:
    std::unique_ptr<Shape> createShape(const std::string& type) {
        if (type == "Circle") {
            return std::make_unique<Circle>();
        } else if (type == "Square") {
            return std::make_unique<Square>();
        } else if (type == "Triangle") {
            return std::make_unique<Triangle>();
        } else {
            return nullptr;
        }
    }
};

int main() {
    ShapeFactory factory;
    
    std::unique_ptr<Shape> circle = factory.createShape("Circle");
    circle->draw();
    
    std::unique_ptr<Shape> square = factory.createShape("Square");
    square->draw();
    
    std::unique_ptr<Shape> triangle = factory.createShape("Triangle");
    triangle->draw();
    
    return 0;
}

프로그램언어 C++에서의 팩토리 패턴 장단점

팩토리 패턴(Factory Pattern)의 장단점

장점:

  • 유연성: 객체 생성 로직을 캡슐화하여 유연한 코드 구조를 제공합니다.
  • 확장성: 새로운 객체 유형을 추가하거나 기존 객체 유형을 변경하기 쉽습니다.
  • 코드 중복 최소화: 객체 생성 코드를 중앙 집중화하여 코드 중복을 방지합니다.
  • 의존성 감소: 클라이언트 코드가 구체 클래스에 직접 의존하지 않고 인터페이스에 의존하게 합니다.

단점:

  • 복잡성: 팩토리 클래스를 추가로 생성해야 하므로 코드의 복잡성이 증가할 수 있습니다.
  • 추가 오버헤드: 객체 생성에 대한 오버헤드가 발생할 수 있습니다.
  • 너무 많은 객체 생성: 과도한 객체 생성으로 성능 저하가 발생할 수 있습니다.

예제 코드:


#include <iostream>
#include <memory>

// Product 인터페이스
class Product {
public:
    virtual void use() = 0;
};

// ConcreteProductA 클래스
class ConcreteProductA : public Product {
public:
    void use() override {
        std::cout << "Using Product A" << std::endl;
    }
};

// ConcreteProductB 클래스
class ConcreteProductB : public Product {
public:
    void use() override {
        std::cout << "Using Product B" << std::endl;
    }
};

// Factory 인터페이스
class Factory {
public:
    virtual std::unique_ptr<Product> createProduct() = 0;
};

// ConcreteFactoryA 클래스
class ConcreteFactoryA : public Factory {
public:
    std::unique_ptr<Product> createProduct() override {
        return std::make_unique<ConcreteProductA>();
    }
};

// ConcreteFactoryB 클래스
class ConcreteFactoryB : public Factory {
public:
    std::unique_ptr<Product> createProduct() override {
        return std::make_unique<ConcreteProductB>();
    }
};

int main() {
    std::unique_ptr<Factory> factoryA = std::make_unique<ConcreteFactoryA>();
    std::unique_ptr<Product> productA = factoryA->createProduct();
    productA->use();

    std::unique_ptr<Factory> factoryB = std::make_unique<ConcreteFactoryB>();
    std::unique_ptr<Product> productB = factoryB->createProduct();
    productB->use();

    return 0;
}
        

프로그램언어 C++의 팩토리 패턴과 다른 디자인 패턴 비교

디자인 패턴은 소프트웨어 개발에서 자주 발생하는 문제를 해결하기 위한 해결책의 모음입니다. C++의 팩토리 패턴과 다른 디자인 패턴을 비교해보겠습니다.

팩토리 패턴 vs 다른 디자인 패턴

1. 팩토리 패턴

팩토리 패턴은 객체 생성을 캡슐화하여 클라이언트에게 직접적인 객체 생성을 숨기고, 객체를 생성하는 인터페이스를 제공합니다. 이는 객체 생성 로직의 변경이나 확장에 용이하며, 코드의 유연성을 높입니다.


class Product {
public:
    virtual void operation() = 0;
};

class ConcreteProduct : public Product {
public:
    void operation() override {
        // 구체적인 동작 정의
    }
};

class Factory {
public:
    virtual Product* createProduct() = 0;
};

class ConcreteFactory : public Factory {
public:
    Product* createProduct() override {
        return new ConcreteProduct();
    }
};

2. 다른 디자인 패턴 (예: 싱글톤 패턴)

싱글톤 패턴은 애플리케이션 전역에서 단일 인스턴스를 유지하는 패턴으로, 객체 생성을 제한하고 해당 객체에 접근하는 방법을 제공합니다. 팩토리 패턴과는 목적과 사용 시점이 다르며, 싱글톤 패턴은 특정 클래스의 인스턴스가 오직 하나만 필요한 경우에 사용됩니다.


class Singleton {
private:
    static Singleton* instance;
    Singleton() {} // 생성자 private로 선언

public:
    static Singleton* getInstance() {
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }
};

Singleton* Singleton::instance = nullptr;

위와 같이 팩토리 패턴은 객체 생성을 추상화하여 유연성을 제공하고, 다른 디자인 패턴인 싱글톤 패턴은 인스턴스 유지를 보장하는데 사용됩니다.

Leave a Comment