프로토타입 패턴(Prototype Pattern)은 객체 생성의 구체적인 클래스를 명시하지 않고, 기존 객체를 복사하여 새로운 객체를 생성하는 방식입니다. 이 패턴은 객체 생성 비용이 큰 경우, 또는 같은 구조의 객체를 여러 개 만들어야 할 때 유용합니다. 프로토타입 패턴은 주로 두 가지 주요 개념으로 구성됩니다: 복사(클론)와 인터페이스.

주요 특징
객체 복사: 기존 객체를 복사하여 새로운 객체를 생성할 수 있습니다. 이 방식은 객체의 생성 비용이 클 때 유용합니다.
유연성: 새로운 객체를 생성할 때, 기존 객체를 기반으로 할 수 있어 유연성이 높습니다.
클라이언트 코드 간소화: 클라이언트는 객체의 구체적인 클래스에 의존하지 않고, 인터페이스를 통해 객체를 복사할 수 있습니다.
C++ 코드 예시
아래는 프로토타입 패턴을 사용하여 도형 객체를 복사하는 예시입니다.
#include <iostream>
#include <string>
#include <unordered_map>
// 프로토타입 인터페이스
class Shape {
public:
virtual Shape* clone() const = 0; // 클론 메서드
virtual void draw() const = 0; // 도형 그리기
virtual ~Shape() {}
};
// 구체 제품 클래스: 원
class Circle : public Shape {
public:
Circle() {}
Circle(const Circle&) {} // 복사 생성자
Shape* clone() const override {
return new Circle(*this); // 현재 객체를 복사하여 새 객체 생성
}
void draw() const override {
std::cout << "Drawing Circle" << std::endl;
}
};
// 구체 제품 클래스: 사각형
class Square : public Shape {
public:
Square() {}
Square(const Square&) {} // 복사 생성자
Shape* clone() const override {
return new Square(*this); // 현재 객체를 복사하여 새 객체 생성
}
void draw() const override {
std::cout << "Drawing Square" << std::endl;
}
};
// 클라이언트 코드
int main() {
// 원과 사각형 객체 생성
Shape* circle = new Circle();
Shape* square = new Square();
// 객체 복사
Shape* circleClone = circle->clone();
Shape* squareClone = square->clone();
// 그리기
circle->draw(); // "Drawing Circle"
square->draw(); // "Drawing Square"
circleClone->draw(); // "Drawing Circle"
squareClone->draw(); // "Drawing Square"
// 메모리 해제
delete circle;
delete square;
delete circleClone;
delete squareClone;
return 0;
}
설명
1. 프로토타입 인터페이스: Shape 클래스는 clone() 메서드와 draw() 메서드를 정의합니다. clone() 메서드는 객체를 복사하는 역할을 합니다.
2. 구체 제품 클래스:
- Circle 클래스와 Square 클래스는 Shape 인터페이스를 구현합니다. 각각의 clone() 메서드는 현재 객체를 복사하여 새로운 객체를 생성합니다.
- draw() 메서드는 각 도형의 정보를 출력합니다.
3. 클라이언트 코드:
main 함수에서는 Circle과 Square 객체를 생성한 후, clone() 메서드를 호출하여 복사본을 생성합니다.
각 객체의 draw() 메서드를 호출하여 도형을 그리는 메시지를 출력합니다.
위 코드를 실행한 결과는 다음과 같다.
Drawing Circle
Drawing Square
Drawing Circle
Drawing Square
실행 과정 설명:
1. 객체 생성:
- Circle 객체와 Square 객체가 각각 생성됩니다.
2. 객체 복사: - circle->clone() 메서드를 호출하여 Circle 객체의 복사본(circleClone)이 생성됩니다.
- square->clone() 메서드를 호출하여 Square 객체의 복사본(squareClone)이 생성됩니다.
3. 도형 그리기: - circle->draw() 호출: "Drawing Circle"이 출력됩니다.
- square->draw() 호출: "Drawing Square"가 출력됩니다.
- circleClone->draw() 호출: 복사된 원의 draw() 메서드가 호출되어 "Drawing Circle"이 출력됩니다.
- squareClone->draw() 호출: 복사된 사각형의 draw() 메서드가 호출되어 "Drawing Square"가 출력됩니다.
다른 예시코드 하나 더 갑니다.
#include <iostream>
#include <memory>
#include <string>
// Prototype 인터페이스
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 r) : radius(r) {}
// 복제 메서드 구현
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 s) : side(s) {}
// 복제 메서드 구현
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() {
// 원형 객체 생성
std::unique_ptr<Shape> circlePrototype = std::make_unique<Circle>(5.0);
std::unique_ptr<Shape> squarePrototype = std::make_unique<Square>(7.0);
// 원형 객체 복제 및 사용
auto clonedCircle1 = circlePrototype->clone();
clonedCircle1->draw();
auto clonedCircle2 = circlePrototype->clone();
clonedCircle2->draw();
auto clonedSquare1 = squarePrototype->clone();
clonedSquare1->draw();
auto clonedSquare2 = squarePrototype->clone();
clonedSquare2->draw();
return 0;
}
1. Prototype 인터페이스 (Shape)
class Shape {
public:
virtual ~Shape() {}
virtual std::unique_ptr<Shape> clone() const = 0;
virtual void draw() const = 0;
};
- Shape 클래스는 추상 클래스로, 모든 도형이 가져야 할 공통 인터페이스를 정의합니다.
- clone() 메서드는 객체를 복제하는 역할을 합니다. 이는 순수 가상 함수로 선언되어 있어, 이를 상속받는 클래스가 반드시 구현해야 합니다.
- draw() 메서드는 도형을 그리는 기능을 정의하며, 역시 순수 가상 함수입니다.
2. Concrete Prototype: Circle
class Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) {}
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;
}
};
- Circle 클래스는 Shape 인터페이스를 구현한 구체적인 프로토타입 클래스입니다.
- 생성자에서 원의 반지름(radius) 값을 초기화합니다.
- 복제 메서드 (clone):
- clone() 메서드는 현재 객체(*this)를 복제하여 새로운 객체를 반환합니다.
- std::make_unique(*this)를 사용하여 깊은 복사를 수행합니다.
- 그리기 메서드 (draw):
- 원의 반지름 값을 출력하며 원을 "그리는" 역할을 합니다.
3. Concrete Prototype: Square
class Square : public Shape {
private:
double side;
public:
Square(double s) : side(s) {}
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;
}
};
- Square 클래스는 Shape 인터페이스를 구현한 또 다른 구체적인 프로토타입 클래스입니다.
- 생성자에서 정사각형의 한 변(side) 길이를 초기화합니다.
- 복제 메서드 (clone):
- 현재 객체를 복제하여 새로운 객체를 반환합니다.
- std::make_unique(*this)를 사용하여 깊은 복사를 수행합니다.
- 그리기 메서드 (draw):
- 정사각형의 한 변 길이를 출력하며 정사각형을 "그리는" 역할을 합니다.
4. Client 코드
int main() {
// 원형 객체 생성
std::unique_ptr<Shape> circlePrototype = std::make_unique<Circle>(5.0);
std::unique_ptr<Shape> squarePrototype = std::make_unique<Square>(7.0);
// 원형 객체 복제 및 사용
auto clonedCircle1 = circlePrototype->clone();
clonedCircle1->draw();
auto clonedCircle2 = circlePrototype->clone();
clonedCircle2->draw();
auto clonedSquare1 = squarePrototype->clone();
clonedSquare1->draw();
auto clonedSquare2 = squarePrototype->clone();
clonedSquare2->draw();
return 0;
}
주요 흐름:
- 원형 객체 생성:
- 클라이언트는 먼저 원형 객체(circlePrototype, squarePrototype)를 생성합니다.
- 각각 반지름이 5인 원과 한 변 길이가 7인 정사각형으로 초기화됩니다.
- 복제 및 사용:
- 클라이언트는 원형 객체의 clone() 메서드를 호출하여 새로운 객체를 복제합니다.
- 복제된 객체(clonedCircle1, clonedCircle2, clonedSquare1, clonedSquare2)는 각각 독립적인 상태를 가지며, 이를 바로 사용할 수 있습니다.
- 복제된 객체에서 draw() 메서드를 호출하여 도형 정보를 출력합니다.
실행 결과 분석
코드 실행 시 다음과 같은 출력이 나타납니다:
Drawing a Circle with radius 5
Drawing a Circle with radius 5
Drawing a Square with side 7
Drawing a Square with side 7
설명:
- 첫 번째와 두 번째 줄은 원형 객체(circlePrototype)에서 복제된 두 개의 원(clonedCircle1, clonedCircle2)을 그린 결과입니다. 두 원은 동일한 반지름(5)을 가집니다.
- 세 번째와 네 번째 줄은 정사각형 원형 객체(squarePrototype)에서 복제된 두 개의 정사각형(clonedSquare1, clonedSquare2)을 그린 결과입니다. 두 정사각형은 동일한 변 길이(7)를 가집니다.
장점
객체 생성 비용이 클 때, 기존 객체를 복사하여 새로운 객체를 생성함으로써 성능을 개선할 수 있습니다.
클라이언트는 객체의 구체적인 클래스에 의존하지 않고, 인터페이스를 통해 객체를 복사할 수 있습니다.
단점
복사할 객체가 복잡한 상태를 가지고 있을 경우, 깊은 복사가 필요할 수 있어 구현이 복잡해질 수 있습니다.
객체의 상태를 복사해야 하므로, 필요한 경우 모든 속성을 수동으로 복사해야 할 수 있습니다.
프로토타입 패턴은 객체 생성의 유연성을 높이고, 복잡한 객체를 쉽게 관리할 수 있도록 도와주는 유용한 디자인 패턴입니다.
'c c++ mfc' 카테고리의 다른 글
디자인패턴 - 팩토리 메소드(Factory Method) (0) | 2025.03.17 |
---|---|
디자인패턴 - 빌더 패턴(Builder Pattern) (0) | 2025.03.17 |
디자인패턴 - 추상 팩토리 패턴(Abstract Factory Pattern) (0) | 2025.03.17 |
Visual Studio 재배포 패키지가 설치되지 않는 문제 해결방법 (2) | 2024.10.11 |
UML Sequence Diagram에서 Boundary, Control, Entity 클래스가 하는 역할은? (0) | 2024.05.09 |