빌더 패턴 정의
=> 객체를 생성할 때 그 객체를 구성하는 부분 부분을 먼저 생성하고, 이를 조합함으로써 객체 전체를 생성하는 방법
=> 생성할 객체의 종류가 손쉽게 추가, 확장이 가능한 설계
=> 복잡한 유형의 오브젝트를 작성하는데 사용된다.
추상 팩토리 패턴과의 차이점
Builder Pattern | Abstract Factory Pattern | |
특징 | 복잡한 객체의 단계별 생성에 중점 | 제품의 유사군들의 존재하는 경우 유연한 설계에 중점 |
반환 시기 | 마지막 단계에서 생성한 제품 반환 | 만드는 즉시 제품을 반환 |
이제 예제를 통해 한 번 알아보자.
예제로 빌더 패턴을 이용해 비행기와 헬리콥터를 만들어 보려한다.
어떻게 쓰는지 한 번 보자.
먼저 프로젝트 정보다.
비행기와 헬리콥터 모두 Engine과 Wing은 가지고 있다.
다만 헬리콥터는 십자 모양으로 Wing을 2개 가지고 있다고 가정하고, 비행기는 1개로 가정하자.
그리고 프레임은 비행기와 헬리콥터가 다를테니 각각 하나씩 프리팹으로 만들었다.
마지막으로 각 부품들을 묶어놓을 부모 객체(빈 객체)를 만든다.
위의 프리팹은 전부 Cube와 Sphere로 만들었다..
또한 색상으로 구분하기 위해 Material 몇 개를 만들어서 적용시켰다.
이제 스크립트를 보자.
// Vehicle.cs
using UnityEngine;
public class Vehicle : MonoBehaviour
{
private VehicleType vehicleType;
public void setVehicleType(VehicleType vehicleType)
{
this.vehicleType = vehicleType;
}
public void AddPart(GameObject part, Vector3 localPosition)
{
GameObject obj = Instantiate(part) as GameObject;
obj.transform.localPosition = localPosition;
obj.transform.SetParent(this.transform);
}
public string GetPartsList()
{
string partsList = vehicleType.ToString() + " parts:\n\t";
Transform[] trs = GetComponentsInChildren<Transform>();
for (int i = 1; i < trs.Length; i++)
partsList += trs[i].gameObject.name + " ";
return partsList;
}
}
먼저 Vehicle.cs이다.
먼저 Vehicle은 각각의 부품을 가지고 있고 AddPart를 통해 부품을 조립해나간다.
GetPartsList는 전체 모인 부품들의 목록을 반환해준다.
// InterfaceBuilder.cs
interface IVehicleBuilder
{
Vehicle getVehicle();
void BuildFrame();
void BuildEngine();
void BuildWings();
}
public enum VehicleType
{
Airplane,
Helicopter
}
그 다음은 Vehicle을 만들기 위한 인터페이스다.
비행기와 헬리콥터에는 모양을 잡을 프레임과, 움직이기 위한 엔진과, 날기 위한 날개가 있다.
그래서 프레임, 엔진, 날개를 만드는 메소드 3개를 가지고 있는 인터페이스를 만들었다.
// AirplaneBuilder.cs
using UnityEngine;
public class AirplaneBuilder : MonoBehaviour, IVehicleBuilder
{
public GameObject ParentOfVehicle;
public GameObject frame;
public GameObject engine;
public GameObject wing;
private Vehicle _vehicle;
public Vehicle getVehicle()
{
return _vehicle;
}
public void makeVehicle()
{
GameObject obj = Instantiate(ParentOfVehicle) as GameObject;
_vehicle = obj.GetComponent<Vehicle>();
_vehicle.setVehicleType(VehicleType.Airplane);
}
public void BuildFrame()
{
_vehicle.AddPart(frame, Vector3.zero);
}
public void BuildEngine()
{
_vehicle.AddPart(engine, new Vector3(0.5f, 0.5f, 0));
}
public void BuildWings()
{
_vehicle.AddPart(wing, new Vector3(0.5f, 0, 0));
}
}
위의 인터페이스를 구현하는 AirplaneBuilder이다.
makeVehicle은 Vehicle클래스를 가져와서 타입을 정해주고 부품들을 모아놓을 빈 게임오브젝트를 만든다.
그리고 인터페이스에 있던 메소드를 부품에 맞게 구현한다.
// HelicopterBuilder.cs
using UnityEngine;
public class HelicopterBuilder : MonoBehaviour, IVehicleBuilder
{
public GameObject ParentOfVehicle;
public GameObject frame;
public GameObject engine;
public GameObject wing;
public GameObject wing2;
private Vehicle _vehicle;
public Vehicle getVehicle()
{
return _vehicle;
}
public void makeVehicle()
{
GameObject obj = Instantiate(ParentOfVehicle) as GameObject;
_vehicle = obj.GetComponent<Vehicle>();
_vehicle.setVehicleType(VehicleType.Airplane);
}
public void BuildFrame()
{
_vehicle.AddPart(frame, Vector3.zero);
}
public void BuildEngine()
{
_vehicle.AddPart(engine, new Vector3(1.5f, 0, 0));
}
public void BuildWings()
{
_vehicle.AddPart(wing, new Vector3(0.5f, 0.8f, 0));
_vehicle.AddPart(wing2, new Vector3(0.5f, 0.8f, 0));
}
}
HelicopHelicopterBuilder.cs도 위와 같다.
// Director.cs
class Engineer
{
public void Construct(IVehicleBuilder vehicleBuilder)
{
vehicleBuilder.BuildFrame();
vehicleBuilder.BuildEngine();
vehicleBuilder.BuildWings();
}
}
Director클래스다.
위에서 인터페이스를 구현해도 자동으로 생성되는건 아니기때문에
이 Director클래스가 위의 비행기와 헬리콥터를 만들어 주어야 한다.
인터페이스를 인자로 받아 무슨 타입이 들어오든간에 Frame, Engine, Wings를 만든다.
// BuilderUse.cs
using UnityEngine;
public class BuilderUse : MonoBehaviour
{
void Start()
{
Engineer engineer = new Engineer();
AirplaneBuilder airplaneBuilder = GetComponent<AirplaneBuilder>();
airplaneBuilder.makeVehicle();
HelicopterBuilder helicopterBuilder = GetComponent<HelicopterBuilder>();
helicopterBuilder.makeVehicle();
// 빌더를 통해 구성해야 할 제품을 입력받아 제품을 구성한다.
engineer.Construct(airplaneBuilder);
engineer.Construct(helicopterBuilder);
// 최종 생산된 제품을 반환받는다.
Vehicle airplain = airplaneBuilder.getVehicle();
Debug.Log(airplain.GetPartsList());
Vehicle helicopter = helicopterBuilder.getVehicle();
Debug.Log(helicopter.GetPartsList());
// 최종 생산된 제품의 위치를 지정한다.
airplain.transform.position = new Vector3(-3.0f, 0, 0);
helicopter.transform.position = new Vector3(3.0f, 0, 0);
}
}
마지막으로 GameManager로 사용하는 스크립트이다.
먼저 조립을 하기 위한 Director와 Builder가 있어야 한다.
그래서 Engineer클래스와 각 Builder를 만들었다.
그리고 빌더를 통해 각각의 제품을 구성한다.
구성이 끝났으면 최종 생상된 제품을 반환받는다.
스크립트는 완료되었고 다시 프로젝트 세팅으로 가보자.
먼저 ParentOfVehicle에 Vehicle.cs를 붙인다.
그리고 GameManager에 각 Builder와 BuilderUse를 붙인다.
각 Builder에는 맞는 프리팹을 연결해준다.
그리고 실행하면 오브젝트들이 부품별로 생성되고 조립 후 완성되면 나오는걸 볼 수 있다.
로그도 확인해보면 부품들의 리스트도 잘 나온다.
'프로그래밍 > 디자인 패턴' 카테고리의 다른 글
추상 팩토리 패턴 (Abstract Factory Pattern) (0) | 2020.05.31 |
---|---|
팩토리 메서드 패턴 (Factory Method Pattern) (0) | 2020.05.26 |
심플 팩토리 패턴 (Simple Factory Pattern) (0) | 2020.05.24 |
스트레티지 패턴 (Strategy Pattern) (0) | 2020.05.20 |
싱글턴 패턴 (Singleton Pattern) (0) | 2020.05.19 |