[디자인패턴] 생성패턴(5) - Prototype Pattern (프로토타입 패턴)

Study/Software Architecture · 2023. 5. 19. 14:55

디자인 패턴 총정리 시리즈의 다섯번째 패턴은 Prototype Pattern입니다.

 

소프트웨어를 설계할 때 확장 가능하고 유연한 프로그램을 구축하기 위해선 재사용성 및 효율성이 있는 객체 생성 프로세스가 갖춰져야 합니다. 이러한 필요를 만족시킬 수 있는 디자인 패턴이 바로 Prototype 패턴입니다. Prototype 패턴을 활용하면 개발자는 기존 객체를 쉽게 복제하고 이를 통해 새로운 객체를 보다 쉽게 생성할 수 있습니다.

 

해당 게시물에서 이러한 Prototype 패턴에 대한 간단한 개념과 사용 예시, 장/단점을 알아보겠습니다.

1. 개요

Prototype Pattern은 객체 Cloning을 가능하게 하는 생성 패턴입니다. 기존 객체를 복제하여 새로운 객체를 생성할 수 있으며, 이 과정에서 복잡한 인스턴스 생성 로직을 필요로 하지 않습니다.

 

해당 패턴은 Prototype, ConcretePrototype, Client 3가지 주요 컴포넌트로 구성되어 있습니다.

2. 예시 - Car Factory

다음은 Prototype 패턴을 사용하여 Shape 클래스를 정의하고, 해당 클래스를 상속받아 메서드를 오버라이딩 하는 예시입니다.

이때 Circle과 Square 클래스가 ConcretePrototype 클래스가 됩니다. Concrete 클래스에 clone 함수를 구현하여 각각 형상의 복사본을 만들어 줄 수 있습니다.

#include <iostream>
#include <string>
#include <memory>

// Prototype base class
class Shape {
public:
    virtual ~Shape() {}
    virtual std::unique_ptr<Shape> clone() const = 0;
    virtual void draw() const = 0;
};

// Concrete Prototype: Circle
class Circle : public Shape {
private:
    double radius;

public:
    Circle(double radius) : radius(radius) {}

    std::unique_ptr<Shape> clone() const override {
        return std::make_unique<Circle>(*this);
    }

    void draw() const override {
        std::cout << "Drawing a circle with radius " << radius << std::endl;
    }
};

// Concrete Prototype: Square
class Square : public Shape {
private:
    double side;

public:
    Square(double side) : side(side) {}

    std::unique_ptr<Shape> clone() const override {
        return std::make_unique<Square>(*this);
    }

    void draw() const override {
        std::cout << "Drawing a square with side " << side << std::endl;
    }
};

int main() {
    // Create prototype objects
    std::unique_ptr<Shape> circlePrototype = std::make_unique<Circle>(5.0);
    std::unique_ptr<Shape> squarePrototype = std::make_unique<Square>(7.0);

    // Clone and draw circles
    std::unique_ptr<Shape> clonedCircle1 = circlePrototype->clone();
    clonedCircle1->draw();

    std::unique_ptr<Shape> clonedCircle2 = circlePrototype->clone();
    clonedCircle2->draw();

    // Clone and draw squares
    std::unique_ptr<Shape> clonedSquare1 = squarePrototype->clone();
    clonedSquare1->draw();

    std::unique_ptr<Shape> clonedSquare2 = squarePrototype->clone();
    clonedSquare2->draw();

    return 0;
}

위의 예시처럼 Client는 circlePrototype->clone()을 통해서 circle 클래스를 손쉽게 복사하여 객체 인스턴스를 생성할 수 있습니다.

 

출력 결과는 다음과 같습니다.

 

 

 

3. 장점

Simplified object creation: 기존 객체를 복제하는 로직을 간단하게 구현할 수 있습니다.

Improved performance: 객체 복제는 일반적으로 새로운 객체를 처음부터 설계하는 것보다 빠르게 구현할 수 있습니다.

Enhanced flexibility: Prototype 패턴을 사용하면, 특정 요구사항에 맞게 복제 객체를 보다 쉽게 변경 및 설정할 수 있습니다.

 

4. 단점

Deep copying Complexity: 복제 대상 객체가 복잡한 내부 구조를 가지고 있다면, 요구사항에 맞는 완벽하게 정확한 복사본을 보장하기 어렵습니다.

Managing object state: 변형 가능한 상태의 객체를 복제할 때 예외사항이 발생할 수 있으므로 신중한 사용이 요구됩니다.

 

5. 결론

Prototype Pattern은 소프트웨어 개발 시 사용할 수 있는 객체 생성에 대한 간단하고 효율적인 접근법을 제공합니다. 해당 패턴을 활용하여 개발자는 코드 재사용성, 성능 최적화, 프로그램 유연성 등을 높일 수 있습니다. 그러나 객체 상태에 따라 복제하는 객체를 다시 한번 점검하는 노력이 필요합니다.

반응형