🎈 프로토타입 패턴 (Prototype Pattern)
• 객체 생성을 위해 다른 객체 복제
→ 새로운 객체 생성보다 기존 객체 복제하는 것이 효율적인 경우
→ 공통된 상태값은 유지, 필욯나 값만 변경
• 복잡한 과정으로 생성된 객체를 복사 생성할 때 유용
→ 재사용성 증가
• 별도로 원형 관리자를 도입해볼 수 있다.
그렇기에 객체 상태값을 접근/변경할 수 있도록 미리 구현 필요
• 디자인 패턴에서 생성 패턴 중 하나이다.
💻 디자인 패턴(Design Pattern)이란?
👨💻 디자인 패턴(Design Pattern)이란? • SW 개발 방법 중에서도 구조적인 문제 해결에 목적을 둔다. • 알고리즘과 같이 특정 문제를 해결하는 Logic 형태보다는 특정 상황에 적용할 수 있는 방
zoosso.tistory.com
[예제 코드] 프로토타입 패턴
#include <iostream>
class Prototype {
public:
virtual Prototype* clone() = 0;
virtual void print() = 0;
virtual void setState(const std::string& state) = 0;
};
class ConcretePrototype : public Prototype {
private:
std::string state;
public:
ConcretePrototype() : state("") {}
ConcretePrototype(const ConcretePrototype& other) {
state = other.state;
}
Prototype* clone() override {
return new ConcretePrototype(*this);
}
void print() override {
std::cout << "상태: " << state << std::endl;
}
void setState(const std::string& newState) override {
state = newState;
}
};
void main() {
// 프로토타입 객체 생성
ConcretePrototype original;
// 원본 객체 상태 설정
original.setState("Original State");
// 프로토타입 객체 복제를 통해 새로운 객체 생성
Prototype* clone = original.clone();
// 복제 객체의 상태 설정
dynamic_cast<ConcretePrototype*>(clone)->setState("Cloned...");
original.print();
clone->print();
// 메모리 정리
delete clone;
}
예시에서는 하나의 상태만을 가지고 있지만
같은 상태로 복제되어 다른 속성 값을 가질 수 있는 것을 볼 수 있다.
[예제 코드] - 프로토타입 적용 X
#include <iostream>
#include <string>
class Knight {
private:
std::string name;
int health;
public:
Knight(const std::string& name, int health) : name(name), health(health) {}
void setName(std::string _name) {
name = _name;
}
void info() {
std::cout << "Knight: " << name << ", Health: " << health << std::endl;
}
};
void main() {
Knight k1("gga mang", 100);
Knight k2 = k1;
k2.setName("harbang");
k1.info();
k2.info();
}
C++의 복사생성자를 이용해서
프로토타입 패턴이 아니더라도 비슷하게 흉내낼 수 있다.
하지만 복제할 때, 복사생성자가 호출되는데
상태값이 바뀌는 런타임 중에 초기값과 이미 달라져 있을 수 있다.
[예제 코드] - 프로토타입 패턴 O
#include <iostream>
#include <string>
class Knight {
private:
std::string name;
int health;
public:
Knight(const std::string& name, int health) : name(name), health(health) {}
Knight* clone() {
return new Knight(*this);
}
void setName(std::string _name) {
name = _name;
}
void info() {
std::cout << "Knight: " << name << ", Health: " << health << std::endl;
}
};
void main() {
Knight originalKnight("gga mang", 100);
Knight* k1 = originalKnight.clone();
Knight* k2 = originalKnight.clone();
k2->setName("harbang");
k1->info();
k2->info();
}
🎈 프로토타입 패턴 장단점
+ 복잡한 객체 초기화 로직 처리에 유용하다.
+ 객체 생성을 위한 클래스의 수를 줄일 수 있다.
+ 유사한 구조나 초기 상태가 유사한 경우 좋다.
+ 객체 상태를 저장/복원해야 할 때, "스냅샷 용도"로도 좋다.
- 객체가 복제되는 것이기에 메모리 관리 필요
- 객체가 다른 객체와 상호 의존성을 가질 경우 복잡해질 수 있다.
[예제 코드]
#include <iostream>
#include <map>
#include <string>
class Unit {
public:
virtual Unit* clone() = 0;
virtual void render() = 0;
virtual void setState(const std::string& state) = 0;
};
class Knight : public Unit {
private:
std::string state;
public:
Knight(const std::string& initialState) : state(initialState) {}
Unit* clone() override {
return new Knight(*this);
}
Knight(const Knight& other) {
state = other.state;
}
void render() override {
std::cout << "Knight State: " << state << std::endl;
}
void setState(const std::string& newState) override {
state = newState;
}
};
class UnitFactory {
private:
std::map<std::string, Unit*> prototypes;
public:
UnitFactory() {
prototypes["Knight"] = new Knight("Default State");
}
Unit* createUnit(const std::string& type) {
return prototypes[type]->clone();
}
};
void main() {
UnitFactory factory;
Unit* knight1 = factory.createUnit("Knight");
Unit* knight2 = factory.createUnit("Knight");
// 주소 비교
if (knight1 != knight2) {
std::cout << "knight1과 knight2는 서로 다른 객체입니다." << std::endl;
}
// 상태 설정
dynamic_cast<Knight*>(knight1)->setState("1 First");
dynamic_cast<Knight*>(knight2)->setState("2 Second");
knight1->render();
knight2->render();
}
→ 서로 다른 Knight가 생성된 것을 확인할 수 있다.
→ 필요에 따라 속성 값을 변경할 수 있다.
🎈 다른 디자인 패턴과 비교
• 데코레이터 패턴
데코레이터 패턴은 객체에 동적으로 새로운 기능을 추가할 때 주료 사용한다.
상속을 사용하지 않고 기능 확장하는 것이 특징이다
싱글톤 패턴는 인스턴스를 오직 하나만 생성하고 전역 접근 지점을 제공한다.
즉, 하나의 객체를 다른 곳에서 공유할 때 사용된다.
반면에 프로토타입 패턴은 유사한 복사본을 만드는 것으로 여러 인스턴스를 복제 생성한다.
[디자인패턴] 싱글턴 패턴
싱글턴(Singleton) 패턴이란? • 단, 하나의 객체를 만들어서 사용 (단일 객체) → 한번 생성되고 프로그램 종료될 때까지 메모리에 상주 • 디자인 패턴(Design Pattern)에서 "생성 패턴"에 해당 • 다른
zoosso.tistory.com
팩토리 패턴은 객체 생성을 캡슐화하여 생성 로직을 숨기는 패턴이다
이를 통해 다양한 클래스 객체를 생성한다.
유사한 객체를 복제하여 초기화하는 프로토타입 패턴과는 활용 차이가 있다.
팩토리 메서드 패턴 (Factory Method)
🎈 팩토리 메서드 패턴(Factory Method Pattern) • 객체 생성 시 확장을 쉽게 하기 위한 설계 방법 강력한 결합 관계는 코드의 수정•변경을 어렵게 한다. • 객체 생성 동작을 별도 클래스로 분리하
zoosso.tistory.com
복합 객체를 단계별로 설정할 때 사용되는 패턴으로
복잡하게 만들어진 객체를 복제할 때 프로토타입 활용 하면 좋다.
심지어 기존 객체 생성을 몰라도 된다.
[디자인 패턴] 빌더 패턴 (Builder Pattern)
🎈 빌더 패턴(Builder Pattern) •빌더 패턴은 생성이 복잡한 객체를 단계적으로 만들 수 있다. → 생성 코드 따로 관리 • 객체 생성을 별도의 다른 클래스에 위임 •생성자 호출 코드를 한 줄로 생
zoosso.tistory.com
'까망 동네 > 디자인 패턴' 카테고리의 다른 글
[디자인패턴] 커맨드 패턴 (Command Pattern) (1) | 2023.11.03 |
---|---|
[디자인패턴] 장식자 패턴 (Decorator) (2) | 2023.11.01 |
[디자인 패턴] 브릿지 패턴 (Bridge Pattern) (3) | 2023.10.28 |
[디자인 패턴] 중재자 패턴 (Mediator Pattern) (0) | 2023.10.22 |
[디자인 패턴] 빌더 패턴 (Builder Pattern) (2) | 2023.10.21 |
댓글