KimMK

팩토리 패턴 본문

C++/디자인 패턴

팩토리 패턴

KimMK 2023. 3. 10. 16:20

디자인 패턴 중 생성 패턴인 팩토리 패턴은 팩토리 메서드 패턴추상 팩토리 패턴으로 나눌 수 있다.

 

1. 팩토리 메서드 패턴

팩토리 메서드 패턴은 상위 클래스에서 객체를 생성하는 인터페이스를 정의하고, 하위 클래스에서 인스턴스를 생성하도록 하는 방식으로 상위에서 인스턴스를 만드는 방법만 결정하고 하위에서 데이터 생성을 조작하는 함수들을 오버라이딩해서 인터페이스와 실제 객체를 생성하는 클래스를 분리할 수 있는 특성을 갖는 디자인 패턴이다.

즉, 클래스의 인스턴스를 만드는 일을 하위 클래스에게 맡기는 것이다.

이 패턴은 객체를 생성하는 방식이나 생성하는 객체의 종류가 변해도 클라이언트 코드를 수정하지 않고 객체를 생성할 수 있게 한다.

 

간단한 예시

class Shape {
public:
    virtual void draw() = 0;
};

class Circle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a circle" << std::endl;
    }
};

class Rectangle : public Shape {
public:
    void draw() override {
        std::cout << "Drawing a rectangle" << std::endl;
    }
};

Shape 클래스와 이를 상속하는 Circle, Rectangle 클래스가 있다고 가정했을 때,

 

class ShapeFactory {
public:
    virtual Shape* createShape() = 0;
};

class CircleFactory : public ShapeFactory {
public:
    Shape* createShape() override {
        return new Circle();
    }
};

class RectangleFactory : public ShapeFactory {
public:
    Shape* createShape() override {
        return new Rectangle();
    }
};

팩토리 클래스(ShapeFactory)는 Shape 객체를 생성하는 메서드를 제공

이를 상속하는 CircleFactory와 RectangleFactory클래스를 생성

 

int main() {
    ShapeFactory* factory = new CircleFactory();
    Shape* shape = factory->createShape();
    shape->draw();
    
    delete shape;
    delete factory;
    
    factory = new RectangleFactory();
    shape = factory->createShape();
    shape->draw();
    
    delete shape;
    delete factory;
    
    return 0;
}

클라이언트 코드에서 팩토리 클래스를 이용해 객체를 생성

 

팩토리 메서드 패턴에서는 객체를 생성하는 메서드를 팩토리 클래스에서 정의하고, 이를 상속하는 팩토리 클래스(Circle, RectangleFactory)에서 해당 객체를 생성하고 반환하는 방식으로 구현한다.
따라서, 클라이언트 코드에서는 구체적인 객체 생성 방식에 대한 정보를 알 필요가 없고, 단지 추상화된 팩토리 클래스를 이용해 객체를 생성하면 된다.

팩토리 메서드 패턴을 이용하면, OCP(개방 폐쇄의 원칙)를 준수할 수 있다.
*OCP: 객체지향설계를 위한 SOLID 원칙 중 하나로 클래스를 만들 때 확장은 가능하지만 추후에 수정할 필요가 없도록 만드는 원칙이다.

 

2. 추상 팩토리 패턴

구체적인 클래스에 의존하지 않고 서로 연관되거나 의존적인 객체들의 조합을 만드는 인터페이스를 제공하는 패턴이다.

추상 팩토리 패턴은 서로 관련된 객체들을 통째로 묶어서 팩토리 클래스로 만들고, 이를 팩토리 조건에 따라 생성하도록 다시 팩토리를 만들어서 객체를 생성한다.

 

간단한 예시

class Color {
public:
    virtual void fill() = 0;
};

class Red : public Color {
public:
    void fill() override {
        std::cout << "Filling with red color" << std::endl;
    }
};

class Blue : public Color {
public:
    void fill() override {
        std::cout << "Filling with blue color" << std::endl;
    }
};

위에서 언급한 팩토리 메서드 패턴에서 Shape 클래스에 추가적으로 Color 클래스와 이를 상속하는 Red, Blue 클래스가 있다고 가정하면,

 

class AbstractFactory {
public:
    virtual Shape* createShape() = 0;
    virtual Color* createColor() = 0;
};

추가적으로 팩토리 클래스(AbstractFactory)를 만들고, 이 클래스는 생성하고자 하는 객체(Shape와 Color)의 종류에 따라 구체적인 팩토리 클래스를 반환함

 

class ShapeFactory : public AbstractFactory {
public:
    Shape* createShape() override {
        return new Circle();
    }
    
    Color* createColor() override {
        return new Red();
    }
};

class ColorFactory : public AbstractFactory {
public:
    Shape* createShape() override {
        return new Rectangle();
    }
    
    Color* createColor() override {
        return new Blue();
    }
};

이를 상속하는 ShapeFactory와 ColorFactory 클래스를 생성

 

 

int main() {
    AbstractFactory* factory = new ShapeFactory();
    Shape* shape = factory->createShape();
    Color* color = factory->createColor();
    shape->draw();
    color->fill();
    
    delete shape;
    delete color;
    delete factory;
    
    factory = new ColorFactory();
    shape = factory->createShape();
    color = factory->createColor();
    shape->draw();
    color->fill();
    
    delete shape;
    delete color;
    delete factory;
    
    return 0;
}

클라이언트 코드에서 팩토리 클래스를 이용해 Shape와 Color 객체를 생성한다.

 

추상 팩토리 패턴에서는 관련된 객체들을 팩토리 클래스로 묶어서 구현한다.
즉, 도형과 색깔의 관계와 같이 서로 관련된 객체들은 하나의 팩토리 클래스에 모아서 구현하고 이를 상속하는 팩토리 클래스에서는 해당 객체들을 생성하고 반환하는 방식으로 구현한다.

클라이언트에서는 구체적인 객체 생성 방식에 대한 정보를 알 필요가 없고 단지 추상화된 팩토리 클래스를 이용해 객체를 생성하면 된다.
추상 팩토리 패턴도 팩토리 메서드 패턴과 마찬가지로 새로운 객체를 추가하고자 할 때 기존 코드의 수정 없이 새로운 객체를 추가할 수 있는 OCP를 준수한다.
또한, 추상 팩토리 패턴은 팩토리 메서드 패턴보다 더 높은 추상화 수준을 가지고 있어 클라이언트 코드와 팩토리 클래스 사이의 결합도를 낮출 수 있다.

 

'C++ > 디자인 패턴' 카테고리의 다른 글

관찰자(Observer) 패턴  (0) 2023.03.14
싱글턴(Singleton) 패턴  (0) 2023.03.12
경량(Flyweight) 패턴  (1) 2023.03.11
디자인 패턴  (0) 2023.03.11
명령(Command) 패턴  (0) 2023.03.11