1. 빌더 패턴이란?
- 객체를 생성할 때, 그 객체를 구성하는 부분 부분을 단계별로 먼저 생성하고, 이를 조합함으로써 객체 전체를 생성한다.
- 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴
- 생성자 오버로딩
- 복잡한 단계로 생성되는 생성자를 더 쉽고 가독성이 높게 생성할 수 있도록 고안된 패턴
- 편리함과 가독성에 중점을 두고 있어 성능상의 큰 차이는 없지만 작업능률에 큰 차이가 있을 수 있음.
2. 빌더 패턴을 사용하는 경우
- 오브젝트의 생성과정이 복잡할 때 이를 간단하게 만들기 위함
- 플레이어 캐릭터의 옷, 무기 등을 조합하고 장착하는 로직을 구현할 때 사용
3. 빌더 패턴의 장점
1) 편리함 : 객체를 생성하는 클래스에서 만들어 해당 클래스에서 인스턴스를 생성하므로 가독성이 좋고, 유지보수가 쉬움
2) 단순함 : 생성과정이 복잡한 인스턴스를 일관된 프로세스로 생성
3) 축소된 생성자 : 멤버 변수의 초기화와 검증을 각각의 멤버 변수별로 분리해서 작성하여 생성자의 크기가 비대해지는 것을 막는다.
4) 간결함 : 디렉터를 사용하여 인스턴스를 만드는 구체적인 과정을 디렉터로 숨기고 클라이언트 코드는 디렉터를 호출하여 코드가 간결해진다.
5) 확장성 : 서로 다른 빌더 구현체를 주입함으로써 동일한 프로세스에서 서로 다른 객체를 생성할 수 있다.
4. 빌더 패턴의 단점
1) 구체적인 인스턴스를 생성하기 전에 반드시 빌더를 생성해야 함.
2) 관리해야 할 클래스가 많아지고 구조가 복잡해질 수 있음.
5. 코드 구현
using System;
namespace StudyCSharp
{
public class Company
{
private string name;
private string field; // 분야
private string phoneNumber;
// 빌더 패턴을 사용하지 않은 경우
public Company(string name, string field, string phoneNumber)
{
if (!field.Equals("전자") && !field.Equals("금융") && !field.Equals("IT"))
{
Console.WriteLine("해당 분야가 없습니다.");
}
if (!phoneNumber.StartsWith("010"))
{
Console.WriteLine("잘못된 번호입니다.");
}
this.name = name;
this.field = field;
this.phoneNumber = phoneNumber;
}
// 빌더 패턴을 사용하는 경우
public Company(CompanyBuilder builder)
{
this.name = builder.name;
this.field = builder.field;
this.phoneNumber = builder.phoneNumber;
}
public void GetInfo()
{
Console.WriteLine("회사명 : " + this.name);
Console.WriteLine("사업 분야 : " + this.field);
Console.WriteLine("회사번호 : " + this.phoneNumber);
Console.WriteLine("---------------------------------");
}
}
// 빌더
public class CompanyBuilder
{
public string name;
public string field; // 분야
public string phoneNumber;
public CompanyBuilder() { }
public CompanyBuilder setName(string name)
{
this.name = name;
return this;
}
public CompanyBuilder setField(string field)
{
if (!field.Equals("전자") && !field.Equals("금융") && !field.Equals("IT"))
{
this.field = "해당 분야가 없습니다.";
}
else
{
this.field = field;
}
return this;
}
public CompanyBuilder setPhoneNumber(string phoneNum)
{
if (!phoneNum.StartsWith("010"))
{
this.phoneNumber = "잘못된 번호입니다.";
}
else
{
this.phoneNumber = phoneNum;
}
return this;
}
public Company GetCompany()
{
return new Company(this);
}
}
// 디렉터 - 빌더를 이용해 객체들을 생성(호출시 디렉터에서 일어나는 구체적인 과정들을 숨길 수 있음)
// 디렉터에서 회사 객체들을 만들어 냄
public class CompanyDirector
{
private CompanyBuilder companyBuilder;
public CompanyDirector()
{
companyBuilder = new CompanyBuilder();
}
public Company GetCompany()
{
return companyBuilder.GetCompany();
}
// 객체 생성 -> 객체 추가에 용이.
public CompanyBuilder AppleCompany()
{
// 메서드 체이닝 -> 생성자가 자기 자신을 리턴해서 가능
companyBuilder = companyBuilder.setName("Apple").setField("IT").setPhoneNumber("010-1111-2222");
return companyBuilder;
}
public CompanyBuilder KBCompany()
{
companyBuilder = companyBuilder.setName("국민은행").setField("금융").setPhoneNumber("010-9999-8888");
return companyBuilder;
}
public CompanyBuilder NoCompany()
{
companyBuilder = companyBuilder.setName("None").setField("none").setPhoneNumber("011-1111-2222");
return companyBuilder;
}
}
class Program
{
static void Main(string[] args)
{
// **빌더 패턴을 사용하지 않는 경우**
Company Company0 = new Company("삼성", "전자", "010-0000-0000");
Company0.GetInfo();
Console.WriteLine("---------------------------------");
// **빌더 패턴을 사용하는 경우**
CompanyDirector companyDirector = new CompanyDirector(); // 디렉터 생성
// 빌더를 이용해 클래스 객체 생성
Company Company1 = companyDirector.AppleCompany().GetCompany();
Company Company2 = companyDirector.KBCompany().GetCompany();
Company Company3 = companyDirector.NoCompany().GetCompany();
// 객체의 정보 출력
Company1.GetInfo();
Company2.GetInfo();
Company3.GetInfo();
// cf) 아래와 같이 한 번에 출력도 가능!
// companyDirector.AppleCompany().GetCompany().GetInfo();
}
}
}
<출력 결과>
<참고 사이트>