Creational Pattern이란?
인스턴스를 만드는 절차를 추상화하여 객체의 표현 방법을 시스템과 분리해준다.
특징
- 시스템이 사용하는 클레스에 대한 구체적인 정보를 캡슐화한다.
- 어떤 객체가 생성되고 어떤 클래스가 객체를 생성하며 생성 시기를 유연하게 결정되게 해준다.
Abstract Factory
목적
상세화된 sub-class를 정의하지 않고 여려 객체를 생성하기 위한 인터페이스 제공
구조
- AbstractFactory : Product를 생성하는 연산(실행)과 인터페이스 제공
- ConcreteFactory: 구체적인 Product를 생성하는 연산(정의) 구현
- AbstractProduct: AbstractFactory가 생성하는 Product가 가져야 하는 인터페이스 제공
- ConcreteProduct: ConcreteFactory가 생성하는 구체적인 Product가 구현 및 AbstractFactory가 정의하는 인터페이스 구현
- Client: AbstractFactory와 AbstractProduct를 사용
활용성
- 객체가 생성되거나 구성: 객체가 나타나는 방식에 상관 없는 시스템을 만들 때(객체가 언제든 바뀔 수 있다.)
- 여러 제품 중 하나를 선택해서 시스템을 만들고 이걸 나중에 바꿔야 할 수도 있을 때
- 관련된 제품 객체들이 함께 사용되도록 설계 되었으며, 객체들의 제약을 외부에서도 유지되게 할 때
- 제품에 대한 클래스 라이브러리 제공 및 인터페이스를 노출 할 때
협력 방법
- ConcreteFactory 클래스 인스턴스 한개가 런타임에 만들어지며, concrete factory는 제품 객체를 생성. 서로 다른 제품 객체들을 생성하려면 서로 다른 concrete factory가 필요하다.
- AbstractFactory는 필요한 제품 객체를 생성하는 책임(구현)을 ConcreteFactory sub-class에 맡긴다.
결과
장점
- 구체적인 클래스 분리
- 제품군 대체의 편리함
- 제품 사이의 일관성
단점
- 새로운 종류의 제품군 제공이 힘들다
구현
- AbstractFactory를 Sigleton으로 정의.
- AbstractFactory는 제품을 생성하기 위한 인터페이스만 제공하며, 생성한는 방법에 대한 정의는 ConcreteFactory에서 한다.
- 확장 가능한 팩토리 정의
예제
AbstractFactory
class StandardFactory{
public:
StandardFactory();
virtual ProductA* MakeProductA() const {return new ProductA}
virtual ProductB* MakeProductB() const {return new ProductB}
virtual ProductC* MakeProductC() const {return new ProductC}
virtual ProductD* MakeProductD(Option* option) const {return new ProductD(option)}
}
AbstractProduct
class StandardProductA{
public:
StandardProductA();
void somethingForA(){
/* do someting... */
};
}
class StandardProductB{
public:
StandardProductB();
void somethingForB(StandardProductA* productA){
/* do someting... */
};
}
ConcreteProduct
class SpecialProductA : public StandardProductA{
public:
SpecialProductA (SpecialFuction specialFunction);
void somethingForA(){
specialFunction();
/* do someting... */
};
}
class SpecialProductB : public StandardProductB{
public:
SpecialProductB (SpecialFuction specialFunction);
void somethingForB(StandardProductA* productA){
specialFunction();
/* do someting... */
};
}
ConcreteFactory
class SpecialFactory : public StandardFactory {
public:
SpecialFactory();
virtual ProductA* MakeProductA() const {return new ProductA(DoSpecial)}
virtual ProductB* MakeProductB() const {return new ProductB(DoSpecial)}
virtual ProductC* MakeProductC() const {return new ProductC}
virtual ProductD* MakeProductD(Option* option) const {return new ProductD(option)}
protected:
Special* DoSpecial() const;
}
Client
Products* CreateProducts(StandardFactory& factory){
ProductA* productA = factory.MakeProductA();
ProductB* productB = factory.MakeProductB();
ProductC* productC = factory.MakeProductC();
Option* option = new Option();
ProductD* productD = factory.MakeProductD(option);
productA->somethingForA();
productB->somethingForB(productA);
productC->somethingForC();
productD->somethingForD();
.
.
.
return Products;
}
//// just use standard case ////
StadardFactory factory;
Products* products = CreateProducts(factory);
//// special use case ////
SpecialFactory factory;
Products* products = CreateProducts(factory);
Builder
목적
복잡한 객체를 생성하는 방법과 표현하는 방법을 정의하는 클래스를 분리하여 생성 절차를 동일하게 한다.
구조
- Builer: Product 부품을 생성하기 위한 추상 인터페이스 제공
- ConcreteBuilder: Builder 클래스에 정의된 인터페이스를 구현
- Director: Builder 인터페이스를 사용하는 객체를 합성
- Product: 생성할 객체를 표현. 복합 객체의 구성 절차 정의
활용성
- 복합 객체의 생성 알고리즘의 조립 방법이 독립적일 때
- 합성 할 객체들의 표현이 서로 다르더라도 생성 절차에서 지원 해야 할 때
협력 방법
- 사용자는 Director 객체를 생성, 생성한 객체를 Builder 객체로 합성
- 제품의 일부가 built 될때 Direcor는 Builder에게 통보
- Builder는 Director의 요청을 처리해서 부품을 추가
- 사용자는 Builder에서 제품 검색
결과
- 제품에 대한 내부 표현의 다향성
- 생성과 표현에 필요한 코드 분리
- 복합 객체 생성 절차의 세분화
구현
- 조합과 구축에 필요한 인터페이스 정의
- 제품에 대한 추상클래스 필요 유무 확인
- Builder에 있는 메서드는 구현을 제공하지 않음
예제
Builder
class ProductBuilder{
public:
virtual void BuildProduct(){}
virtual void BuildProductItem(){}
virtual void BuildProductBox(){}
virtual Products* GetProduct() { return 0 };
protected:
ProductsBuilder();
}
ConcreteBuilder
class StandardProductBuilder : public ProductBuilder{
public:
StandardProductBuilder(){
_currentProduct = 0;
};
void BuildProduct(){
_currentProduct = new Product;
}
void BuildProductItem(){
Item* item = new Item();
_currentProduct->AddItem(item);
}
void BuildProductBox(){
Box* box = new Box();
_currentProduct->SetBox(box)
}
Product* GetProducts() {
return _currentProduct
}
private:
Product* _currentProduct;
}
Director
class ProductProvider{
public:
/* 다른거 */
Product* CreateProduct(ProductBuilder& builder){
builder.BuildProduct();
builder.BuildItem();
builder.BuildBox();
return builder.GetProduct();
}
}
Builder pattern에서 product와 builder를 합쳐서 다음과 같이 할 수도 있다.
class Product{
public:
Product(){
_item = 0;
_box = 0;
}
Product* SetItem(Item* item){
_item = item;
return this;
}
Product* SetBox(Box* box){
_box = box;
return this;
}
private:
Item* _item;
Box* _box
}
사용 예시
class ProductProvider{
public:
/* 다른거 */
Product* CreateProduct(){
Product* product = new Product();
return product->SetItem(new Item)
->SetBox(new Box);
}
}
728x90