하루의 쉼터

[CreationalPatterns] Builder Pattern 본문

프로그래밍/DesinPattern

[CreationalPatterns] Builder Pattern

Changun An 2023. 4. 15. 03:59
반응형

| OutLine. 점층적 생성자 패턴 (Telescoping Constructor Pattern)
   │─ 특징
   │─ 장점
   │─ 단점
   │─ Class Diagram
   │─ 구성
   │─ 코드 With.C++
   │─ Result(후기)
   └─ Github

복잡한 생성 과정의 객체를 생성과 구현을 분리하고 동일한 로직의 생성을 거쳐 결과를 만들어냄.

특징

  • 객체 생성 과정을 인터페이스 클래스와 구현 클래스로 분리하여 유연함.
  • 객체 생성 과정을 캡슐화하여 생성하는 방식을 추상화함.
  • 객체 생성 과정에서 필요 매개변수를 검사하고 생성함.

장점

  • 인터페이스를 통하여 재구현하는 방식으로 동일한 로직에 다른 객체 생성이 가능
  • 유연하여 재사용성이 높아 유지보수에 유리
  • 객체 생성 과정에서 인터페이스를 활용하여 오류 방지
  • 복잡한 생성 구조를 분리하여 가독성이 좋음.

단점

  • 객체 생성이 복잡하지 않은 경우 코드가 지저분해짐.
  • 관리할 클래스가 많아짐.

Class Diagram

구성

  1. Procuct (생성될 객체)
    1. Builder 패턴에서 생성 될 객체
    2. Concrete Builder를 통하여 생성됨.
  2. Builder (빌더 - 구성해야할 인터페이스)
    1. 인터페이스 클래스 ( 추상클래스 )
  3. Concrete Builder (구현 빌더 - 구현 클래스)
    1. 구현 클래스
    2. 생성 시 필요한 로직을 구현
  4. Director (감독, 관리)
    1. Product 객체를 관리하며, 인터페이스를 받아 생성하고 Concrete Builder를 유연하게 선택 가능
    2. 인터페이스를 사용하여 객체 생성 순서를 결정
    3. 인터페이스를 통하여 여러 클래스를 동적으로 생성 변경 가능.
  • 처음 이 패턴을 봤을 때는 Concrete Builder에서 생성한 로봇을 반환하면 굳이 Director 클래스를 사용하지 않아도 되지 않나 하였으나, Director 클래스를 통해 생성 과정이나 방법을 결정할 수 있고, Concrete Builder에 변경이 일어나도 Client(사용자) 코드는 변경이 최소화 되는 이점이 있음.

 

코드 - With. C++

Product - Robot.hpp

#pragma once
#include<iostream>
// builder
/**
* @brief Robot Builder
*/
class Robot{
	private:
		std::string m_model_name;
		float m_max_vel;
		float m_max_angle;
		float m_min_vel;
		float m_min_angle; 
	public:
		Robot();
		void fn_set_model_name(std::string model_name);
		void fn_set_max_vel(float max_vel);
		void fn_set_max_angle(float max_angle);
		void fn_set_min_vel(float min_vel);
		void fn_set_min_angle(float min_angle);
		virtual ~Robot();
		void fn_print_all();
};

Product - Robot.cpp

#include "Robot.hpp"
Robot::Robot() : m_model_name("Defualt"), m_max_vel(0),m_max_angle(0),m_min_vel(0),m_min_angle(0){

}
void Robot::fn_set_model_name(std::string model_name){
	m_model_name = model_name;
}
void Robot::fn_set_max_vel(float max_vel){
	m_max_vel = max_vel;
}
void Robot::fn_set_max_angle(float max_angle){
	m_max_angle = max_angle;
}
void Robot::fn_set_min_vel(float min_vel){
	m_min_vel = min_vel;
}
void Robot::fn_set_min_angle(float min_angle){
	m_min_angle = min_angle;
}
Robot::~Robot() {
}
void Robot::fn_print_all() {
	std::cout << "model_name : " << m_model_name << " max_vel : " << m_max_vel << " max_angle : " << m_max_angle << " min_vel : " << m_min_vel << " min_angle : " << m_min_angle << std::endl;
}

Builder - IRobotBuilder.hpp

#pragma once
class IRobotBuilder {
public:
	virtual void fn_set_model_name() = 0;
	virtual void fn_set_max_vel() = 0;
	virtual void fn_set_max_angle() = 0;
	virtual void fn_set_min_vel() = 0;
	virtual void fn_set_min_angle() = 0;
	virtual Robot* fn_get_robot() = 0;
};

Concrete Builder - TurtlebotConcreteBuilder.hpp

#pragma once
#include"Robot.hpp"
#include"IRobotBuilder.hpp"
class TurtlebotConcreteBuilder : public IRobotBuilder {
	public :
		TurtlebotConcreteBuilder();
		void fn_set_model_name();
		void fn_set_max_vel();
		void fn_set_max_angle(); 
		void fn_set_min_vel();
		void fn_set_min_angle();
		Robot* fn_get_robot();
	private :
		Robot* robot;
};

Concrete Builder - TurtlebotConcreteBuilder.cpp

#include "TurtlebotConcreteBuilder.hpp"
TurtlebotConcreteBuilder::TurtlebotConcreteBuilder(){
	robot = new Robot();
}
void TurtlebotConcreteBuilder::fn_set_model_name(){
	robot->fn_set_model_name("Turtlebot");
}
void TurtlebotConcreteBuilder::fn_set_max_vel(){
	robot->fn_set_max_vel(10);
}
void TurtlebotConcreteBuilder::fn_set_max_angle(){
	robot->fn_set_max_angle(20);
}
void TurtlebotConcreteBuilder::fn_set_min_vel(){
	robot->fn_set_min_vel(3);
}
void TurtlebotConcreteBuilder::fn_set_min_angle(){
	robot->fn_set_min_angle(10);
}
Robot* TurtlebotConcreteBuilder::fn_get_robot(){
	return robot;
}

Concrete Builder - ChangunbotConcreteBuilder.hpp

#pragma once
#include"Robot.hpp"
#include"IRobotBuilder.hpp"
class ChangunbotConcreteBuilder : public IRobotBuilder {
public:
	ChangunbotConcreteBuilder();
	void fn_set_model_name();
	void fn_set_max_vel();
	void fn_set_max_angle();
	void fn_set_min_vel();
	void fn_set_min_angle();
	Robot* fn_get_robot();
private :
	Robot* robot;
};

Concrete Builder - ChangunbotConcreteBuilder.cpp

#include "ChangunbotConcreteBuilder.hpp"
ChangunbotConcreteBuilder::ChangunbotConcreteBuilder() {
	robot = new Robot();
}
	
void ChangunbotConcreteBuilder::fn_set_model_name(){
	robot->fn_set_model_name("Changunbot");
}

void ChangunbotConcreteBuilder::fn_set_max_vel(){
	robot->fn_set_max_vel(50);
}

void ChangunbotConcreteBuilder::fn_set_max_angle(){
	robot->fn_set_max_angle(30);
}

void ChangunbotConcreteBuilder::fn_set_min_vel(){
	robot->fn_set_min_vel(2);
}

void ChangunbotConcreteBuilder::fn_set_min_angle(){
	robot->fn_set_min_angle(5);
}

Robot* ChangunbotConcreteBuilder::fn_get_robot(){
	return robot;
}

Director - RobotDirector.hpp

#pragma once
#include"Robot.hpp"
#include"IRobotBuilder.hpp"
class RobotDirector{
public :
	void fn_set_robot_builder(IRobotBuilder* robot_builder);
	Robot* fn_build();
private :
	IRobotBuilder* m_robot_builder;
};

Director - RobotDirector.cpp

#include "RobotDirector.hpp"
void RobotDirector::fn_set_robot_builder(IRobotBuilder* robot_builder){
	m_robot_builder = robot_builder;
}

Robot* RobotDirector::fn_build()
{
	m_robot_builder->fn_set_model_name();
	m_robot_builder->fn_set_max_vel();
	m_robot_builder->fn_set_max_angle();
	m_robot_builder->fn_set_min_vel();
	m_robot_builder->fn_set_min_angle();
	return m_robot_builder->fn_get_robot();
}

main.cpp

#include "TurtlebotConcreteBuilder.hpp"
#include "ChangunbotConcreteBuilder.hpp"
#include "Robot.hpp"
#include "RobotDirector.hpp"

int main() {
	RobotDirector robot_director;
	RobotDirector changunbot_director;
	TurtlebotConcreteBuilder turlebot;
	ChangunbotConcreteBuilder changunbot;
	robot_director.fn_set_robot_builder(&turlebot);
	changunbot_director.fn_set_robot_builder(&changunbot);
	Robot* robot_turlebot = robot_director.fn_build();
	Robot* robot_changunbot = changunbot_director.fn_build();
	robot_turlebot->fn_print_all();
	robot_changunbot->fn_print_all();
}

 

Result

클래스 구성도 좋고 인터페이스를 활용하여 유연성도 좋으며 같은 로직으로 다른 객체를 생성해낼 수 있어서 유용함.

다만 관리할 클래스가 많아지므로 생성이 복잡하지 않은 구조에서는 다른 생성 패턴을 쓰는게 유리해보임.

GitHub 

https://github.com/Anchangun/cpp_study/tree/DesinPattern/DesinPattern/BuilderPattern

 

GitHub - Anchangun/cpp_study: Modern c++ 14 Target Sutdy repository

Modern c++ 14 Target Sutdy repository. Contribute to Anchangun/cpp_study development by creating an account on GitHub.

github.com

 

반응형
Comments