but, 팩토리, 팩토리 메서드, 추상 팩토리 → 복합 객체 생성 불가
⇒ 기존 생성 패턴의 한계 ⇒ 복합 객체 생성 처리를 위한 또 다른 패턴이 필요해짐
//////////////////// Computer.h ////////////////////
#include <vector>
#include "Cpu.h"
#include "Memory.h"
#include "Storage.h"
#ifndef COMPUTER_H
#define COMPUTER_H
class Computer
{
private:
// 프로퍼티
Cpu _cpu;
vector<Memory> _ram;
vector<Storage> _storage;
public:
// 메서드
Computer();
~Computer();
string to_string();
float memory();
float storage();
};
#endif
//////////////////// Computer.cpp ////////////////////
#include <iostream>
#include "./header/Computer.h"
using namespace std;
Computer::Computer(){}
Computer::~Computer(){}
string Computer::to_string(){
return "이 컴퓨터의 사양\nCPU = " + _cpu.get() + "\n" +
"Ram = " + std::to_string(memory()) + " GB\n" +
"Storage = " + std::to_string(storage()) + " GB\n";
}
float Computer::memory(){
float size = 0.0f;
for (int i = 0; i < _ram.size(); i++)
{
size += _ram[i].get_size();
}
return size;
}
float Computer::storage(){
float size = 0.0f;
for (int i = 0; i < _storage.size(); i++)
{
size += _storage[i].get_size();
}
return size;
}
복합 객체 - 다른 클래스의 객체를 포함
디자인 패턴에서 복합 객체 구성 :
의존성 주입 형태를 권장
- 의존성 주입이 이루어진 객체들 →
복합 객체의 내부 프로퍼티에 저장
→ 프로퍼티에 저장된 객체 - 속성에 따라 접근 제한이 가능
→ public : 복합 객체와 연결된 객체에 제한없이 접근 가능
#ifndef MEMORY_H
#define MEMORY_H
class Memory
{
private:
float _size;
public:
Memory():Memory(0){};
Memory(float _s) { _size = _s; };
~Memory(){};
void set_size(float _s = 0){ _size = _s;};
float get_size(){ return _size; };
};
#endif
#ifndef STORAGE_H
#define STORAGE_H
class Storage
{
private:
float _size;
public:
Storage():Storage(0){};
Storage(float _s){ _size = _s;};
~Storage(){};
void set_size(float _s = 0){ _size = _s;};
float get_size(){ return _size; };
};
#endif
⇒ 빌더 패턴은 복합 객체 생성 과정을 별도의 독립된 클래스로 관리
// AbstractBuilder.h
#include "BuilderAlgorithm.h"
#pragma once
class AbstractBuilder
{
protected:
BuilderAlgorithm* p_algorithm; // 알고리즘 객체
public:
AbstractBuilder();
~AbstractBuilder();
void set_algorithm(BuilderAlgorithm* algorithm){ p_algorithm = algorithm; };
void get_instance(){ p_algorithm->get_instance(); };
// 추상 메서드 선언, 복합 객체 생성 로직을 하위 클래스에 위임
virtual void build();
};
// ConcreteBuilder.h
#include "AbstractBuilder.h"
#include <iostream>
using namespace std;
#pragma once
class ConcreteBuilder : public AbstractBuilder
{
public:
ConcreteBuilder(){};
ConcreteBuilder(BuilderAlgorithm* algorithm){ set_algorithm(algorithm); };
~ConcreteBuilder(){};
AbstractBuilder* build();
};
// ConcreteBuilder.cpp
#include "./header/ConcreteBuilder.h"
AbstractBuilder* ConcreteBuilder::build(){
cout << "Build start.\n";
// 단계별 빌더의 메서드 호출
this->p_algorithm->set_cpu();
this->p_algorithm->set_ram();
this->p_algorithm->set_storage();
return this;
}
각각의 단계를 구조화 → 객체를 생성할 수 있는 로직으로 전달
// BuilderAlgorithm.h
#pragma once
class AbstractBuilder;
class BuilderAlgorithm // 알고리즘의 공통된 동작을 위한 추상 클래스 선언
{
protected:
AbstractBuilder* p_composite; // 빌더 객체를 저장
public:
BuilderAlgorithm();
~BuilderAlgorithm();
virtual void set_cpu(); // 객체 생성에 필요한 추상 메서드 선언
virtual void set_ram(); // -> 각 알고리즘으로 재정의될 것
virtual void set_storage();
virtual AbstractBuilder* get_instance() { return this->p_composite; };
};
객체 생성에 필요한 추상 메서드 선언,
공통된 로직은 메서드나 프로퍼티로 연결될 수 있음
복합 객체의 생성 알고리즘 분리
→ 내부 구조를 외부로부터 보호 가능
#include "header/ConcreteAlgorithm.h"
#include <iostream>
using namespace std;
ConcreteAlgorithm::ConcreteAlgorithm(){
Computer comp;
p_composite = ∁
}
ConcreteAlgorithm::~ConcreteAlgorithm(){}
void ConcreteAlgorithm::set_cpu(std::string cpu) {
p_composite->_cpu = Cpu(cpu);
}
void ConcreteAlgorithm::set_ram(vector<float> rams){
for (int i = 0; i < rams.size(); i++)
{
p_composite->_ram.push_back(Memory(rams[i]));
}
}
void ConcreteAlgorithm::set_storage(vector<float> storages){
for (int i = 0; i < storages.size(); i++)
{
p_composite->_storage.push_back(Storage(storages[i]));
}
}
복합 객체 생성을 위한 단계별 행동이 정의
→ 이러한 과정의 조합→ 실제 제품 생산 시 or 중간 과정 확장 시 매우 유용
#include "./header/ConcreteBuilder.h"
AbstractBuilder* ConcreteBuilder::build(){
cout << "Build start.\n";
// 단계별 빌더의 메서드 호출
cout << get_algorithm() << "\n";
get_algorithm()->set_cpu("i7");
cout << "add cpu" <<'\n';
vector<float> rams = {16, 16};
get_algorithm()->set_ram(rams);
cout << "add ram" <<'\n';
vector<float> storages = {1024, 1024};
get_algorithm()->set_storage(storages);
cout << "add storage" <<'\n';
return this;
}
⇒ 생성 단계를 위한 알고리즘(=처리 로직) 전략 패턴으로 전달
→ 다양한 종류의 복합 객체를 쉽게 생성할 수 있게 됨.
→ 전략 패턴을 적용한 빌더 패턴 - 생성자를 통해 알고리즘 객체를 전달(의존성) 받음
⇒ 빌더 클래스
복합 객체를 제작하는 빌더 객체 생성
→ 빌더 패턴 내부에 복합 객체 생성을 수행하는 알고리즘이 있음
→ 알고리즘은 전략 패턴을 결합하여 구현 동장
전랙 패턴인 알고리즘을 빌더의 생성자로 하여 의존성 주입
→ 생성자로 의존성 주입되면 입력된 알고리즘으로 복합 객체 생성을 동적으로 수행
클라이언트 코드에서 최종 복합 객체 생성
→ 클라이언트 코드 - 빌더 객체에 실제 복합 객체 생성을 요청
→ 빌더는 의존성 주입된 알고리즘에 따라 복합 객체 생성