Builder Pattern

Posted at 2006. 10. 9. 23:01 | Posted in 프로그래밍/ASP, Javascript


Builder pattern은 클라이언트 객체가 단지 타입과 내용을 정의하는것만으로 복잡한 객체를 생성하도록 해준다. 클라이언트는 객체 생성의 세부사항들로부터 보호된다.

이것은 복잡한 객체를 단계별로 생성하기 위한 패턴이며, 동일한 생성 과정으로 여러가지를 표현할 수 있다는 것은 생성 과정을 좀 더 잘 다루도록 하는 builder pattern에서의 루틴이다.  다른 builder는 일반적으로 builder가 product를 부분적으로 만들기 위해 디렉터가 사용하는 일반함수를 정의하는 abstract builder 클래스에서 상속된다.

Builder는 abstract factory와 비슷한 생성동기를 가지지만, 패턴과는 다르게, 클라이언트는 자신의 객체를 생성하기 위해서 abstract factory class methods를 사용하고, builder에서 클라이언트는 builder class에게 객체를 생성하는법을 지시하고, 결과를 요청한다. 모아진 클래스가 어떻게 빌더클래스가 되는가? 여기엔 미묘한 차이점이 있다.

Builder pattern은 복잡한 객체를 생성하기 위한 알고리즘이 객체를 구성하는 부분들에 독립적이어야 하고 조합방법과 생성과정이 만들어진 객체에게 여러가지를 표현할 수 있도록 할 때 적용할 수 있다.


예제

다음은 집을 짓는 예제이다. 클라이언트는 디렉터에게(CDirector class) boolean parameter(blnBackyard)를 지니는 BuildHouse를 호출함으로써 집을 만들 것을 요구한다. 그러면 디렉터는 blnBackyard가 false거나 Single Family home(Concrete Builder)이면 아파트를 만들고, blnBackyard가 true이면(둘다 IHouse interface를 실행한다) IHouse (Abstract Builder) 인터페이스를 리턴한다.
디렉터는 복잡한 집짓기를 하고, 클라이언트는 집생성, 방, 뒷뜰등에 대한 걱정할 필요없이 IHouse 언터페이스를 돌려받는다.

Diagram




C# Implementation
[CODE type=c#]
using System;
using System.Collections;
public interface IHouse
{
bool GetBackyard();
long NoOfRooms();
string Discription();
}

public class CApt:IHouse
{
private bool mblnBackyard;
private Hashtable Rooms;

public CApt()
{
CRoom room;
Rooms = new Hashtable();
room = new CRoom();
room.RoomName = "Master Bedroom";
Rooms.Add ("room1",room);
room = new CRoom();
room.RoomName = "Second Bedroom";
Rooms.Add ("room2",room);
room = new CRoom();
room.RoomName = "Living Room";
Rooms.Add ("room3",room);
mblnBackyard = false;
}

public bool GetBackyard()
{
return mblnBackyard;
}
public long NoOfRooms()
{
return Rooms.Count;
}
public string Discription()
{
IDictionaryEnumerator myEnumerator = Rooms.GetEnumerator();
string strDiscription;
strDiscription = "This is an Apartment with " + Rooms.Count + " Rooms \n";
strDiscription = strDiscription + "This Apartment doesn't have a backyard \n";
while (myEnumerator.MoveNext())
{
strDiscription = strDiscription + "\n" + myEnumerator.Key + "\t" + ((CRoom)myEnumerator.Value).RoomName;
}
return strDiscription;
}
}

public class CSFH:IHouse
{
private bool mblnBackyard;
private Hashtable Rooms;
public CSFH()
{
CRoom room;
Rooms = new Hashtable();
room = new CRoom();
room.RoomName = "Master Bedroom";
Rooms.Add ("room1",room);
room = new CRoom();
room.RoomName = "Second Bedroom";
Rooms.Add ("room2",room);
room = new CRoom();
room.RoomName = "Third Room";
Rooms.Add ("room3",room);
room = new CRoom();
room.RoomName = "Living Room";
Rooms.Add ("room4",room);
room = new CRoom();
room.RoomName = "Guest Room";
Rooms.Add ("room5",room);
mblnBackyard = true;
}

public bool GetBackyard()
{
return mblnBackyard;
}

public long NoOfRooms()
{
return Rooms.Count;
}
public string Discription()
{
IDictionaryEnumerator myEnumerator = Rooms.GetEnumerator();
string strDiscription;
strDiscription = "This is an Single Family Home with " + Rooms.Count + " Rooms \n";
strDiscription = strDiscription + "This house has a backyard \n";
while (myEnumerator.MoveNext())
{
strDiscription = strDiscription + "\n" + myEnumerator.Key + "\t" + ((CRoom)myEnumerator.Value).RoomName;
}
return strDiscription;
}
}

public interface IRoom
{
string RoomName{get;set;}
}

public class CRoom:IRoom
{
private string mstrRoomName;
public string RoomName
{
get
{
return mstrRoomName;
}
set
{
mstrRoomName = value;
}
}
}

public class CDirector
{
public IHouse BuildHouse(bool blnBackyard)
{
if (blnBackyard)
{
return new CSFH();
}
else
{
return new CApt();
}
}
}

public class Client
{
static void Main(string[] args)
{
CDirector objDirector = new CDirector();
IHouse objHouse;
objHouse = objDirector.BuildHouse(bool.Parse(args[0]));
Console.WriteLine(objHouse.Discription());
}
}
[/HTML][/CODE]



//