Contents
1. Builder Pattern ¶
1.2. 실ìƒ�활ì—� ì �ìš©ë�˜ëŠ” 쉬운 예 ¶
패스트(ì •í�¬)푸드 ë ˆìŠ¤í† ëž‘ ë§¥ë�„ë‚ ë“œì—�서 어린ì�´ìš© 해피밀ì�„ 만들어내는 걸로 예를 들 수 있다. ì�¼ë°˜ì �으로 해피밀ì�€ ë©”ì�¸, 사ì�´ë“œ, ì�Œë£Œ, 장난ê°� (햄버거, 프ë�¼ì�´, 콜ë�¼, 매달 바뀌는 장난ê°�)으로 ì�´ë£¨ì–´ì ¸ 있다. 여기서 중요한건, ì�´ëŸ° 템플릿ì�´ ì •í•´ì ¸ 있다는 것ì�´ë‹¤. 요즘 ê°™ì�´ 까다로운 ì•„ì�´ë“¤ì—�게 어릴때부터 ë§¥ë�„ë‚ ë“œì�˜ ìž…ë§›ì�„ 확실히 ë“¤ì—¬ë†“ìœ¼ë ¤ë©´ 당연히 다양한 바리ì—�ì�´ì…˜ì�´ 필요하다. ê³ ê°�ì�€ 햄버거나 치즈버거나, 아니면 맥너겟ì�´ë‚˜ ì�´ëŸ°ê±¸ ì„ íƒ�í• ìˆ˜ 있지만, 기본ì �으로 해피밀ì�´ 구성ë�˜ëŠ” ë°©ì‹�ì—�는 변함 없다. 여기서 빌ë�” 패턴ì�„ ì �용한다면, ì¹´ìš´í„°ì—�서 주문ì�„ 받는 ì§�ì›�ì�„ Director ë�¼ê³ í• ìˆ˜ 있다. ë¬¼ë¡ ê³ ê°�ì�€ Customer ì�´ë‹¤. ê³ ê°�ì�´ ì›�하는 바리ì—�ì�´ì…˜ì�„ ì„ íƒ�해서 해피밀 셋트를 구성하게 ë�˜ë©´ (Customerê°€ Concrete Builder 를 ì„ íƒ�한다) Director 는 ì •í•´ì§„ 템플릿ì—� ë”°ë�¼ 주방 ì§�ì›�(Concrete Builder) ì—�게 ì�˜ë¢°í•˜ì—¬ 해피밀 세트(Product) 를 만들어 낸다. 여기서 Director ê°€ Concrete Builder ì—�게 요구하는 ë°©ì‹�ì�€ 종류ì—� ë”°ë�¼ 비슷 하므로 그것ì�„ ì¶”ìƒ�화시킨 ì�¸í„°íŽ˜ì�´ìŠ¤ë¥¼ Builder ë�¼ê³ í• ìˆ˜ ìžˆê² ë‹¤.
1.3.2. Concrete Builder ¶
Builder 를 구현한 부분. ì�¼ë°˜ì �으로 다수개ì�˜ Concrete Builder ê°€ 존재하며, Builder ê°€ ì œê³µí•˜ëŠ” ì�¸í„°íŽ˜ì�´ìŠ¤ë¥¼ ì�´ìš©í•´ì„œ late binding ì�˜ 형ì‹�으로 사용하게 ë�œë‹¤. ë¬¼ë¡ , builder pattern ì—�서ì�˜ 주 관심하는 Product 를 만들어내는 것ì�´ë‹¤.
1.3.3. Director ¶
Director í�´ëž˜ìŠ¤ëŠ” Product 를 ìƒ�성하는 방법과 순서 등ì�„ 주관한다. Builder ì�¸ìŠ¤í„´ìŠ¤ë¥¼ ê°€ì§€ê³ ìžˆê¸° 때문ì—� Concrete Builder 를 건네 받아서 Builder ì—� ì—°ê²°í•´ 준다.
1.3.4. Product ¶
만들어야 í• ëŒ€ìƒ�. ì�¼ë°˜ì �으로 Builder Pattern ì�´ ìƒ�성하는 Product 는 Composite Pattern 으로 ì�´ë£¨ì–´ì§„다.
1.4.1. Wikipedia ì�˜ Java code ¶
/** "Product" */
class Pizza {
private String dough = "";
private String sauce = "";
private String topping = "";
public void setDough (String dough) { this.dough = dough; }
public void setSauce (String sauce) { this.sauce = sauce; }
public void setTopping (String topping) { this.topping = topping; }
}
/** "Abstract Builder" */
abstract class PizzaBuilder {
protected Pizza pizza;
public Pizza getPizza() { return pizza; }
public void createNewPizzaProduct() { pizza = new Pizza(); }
public abstract void buildDough();
public abstract void buildSauce();
public abstract void buildTopping();
}
/** "ConcreteBuilder" */
class HawaiianPizzaBuilder extends PizzaBuilder {
public void buildDough() { pizza.setDough("cross"); }
public void buildSauce() { pizza.setSauce("mild"); }
public void buildTopping() { pizza.setTopping("ham+pineapple"); }
}
/** "ConcreteBuilder" */
class SpicyPizzaBuilder extends PizzaBuilder {
public void buildDough() { pizza.setDough("pan baked"); }
public void buildSauce() { pizza.setSauce("hot"); }
public void buildTopping() { pizza.setTopping("pepperoni+salami"); }
}
/** "Director" */
class Waiter {
private PizzaBuilder pizzaBuilder;
public void setPizzaBuilder (PizzaBuilder pb) { pizzaBuilder = pb; }
public Pizza getPizza() { return pizzaBuilder.getPizza(); }
public void constructPizza() {
pizzaBuilder.createNewPizzaProduct();
pizzaBuilder.buildDough();
pizzaBuilder.buildSauce();
pizzaBuilder.buildTopping();
}
}
/** A customer ordering a pizza. */
class BuilderExample {
public static void main(String[] args) {
Waiter waiter = new Waiter();
PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();
waiter.setPizzaBuilder ( hawaiianPizzaBuilder );
waiter.constructPizza();
Pizza pizza = waiter.getPizza();
}
}
1.4.2. Composite Pattern ì�„ ìƒ�성해주는 Builder Pattern ì˜ˆì œ 코드 ¶
Head First Design Pattern � 나오는, Vacation Planner 를 구현한 코드
1.4.2.1. nijel.product ¶
// PlanComponent
package nijel.product;
public class PlanComponent {
protected String name;
protected String description;
public PlanComponent(String name, String description) {
this.name = name;
this.description = description;
}
public void add(PlanComponent planComponent) {
throw new UnsupportedOperationException();
}
public void remove(PlanComponent planComponent) {
throw new UnsupportedOperationException();
}
public PlanComponent getChild(int index) {
throw new UnsupportedOperationException();
}
public String getName() {
throw new UnsupportedOperationException();
}
public String getDescription() {
throw new UnsupportedOperationException();
}
public void print() {
throw new UnsupportedOperationException();
}
}
// Plan
package nijel.product;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Plan extends PlanComponent {
private List<PlanComponent> planComponents;
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public Plan(String name, String description) {
super(name, description);
planComponents = new ArrayList<PlanComponent>();
}
public void add(PlanComponent planComponent) {
planComponents.add(planComponent);
}
public PlanComponent getChild(int index) {
return planComponents.get(index);
}
public void remove(PlanComponent planComponent) {
planComponents.remove(planComponent);
}
public void print() {
System.out.println("\n" + getName());
System.out.println(", " + getDescription());
System.out.println("------------------------------");
Iterator iterator = planComponents.iterator();
while (iterator.hasNext()) {
PlanComponent planComponent = (PlanComponent) iterator.next();
planComponent.print();
}
}
}
// PlanItem
package nijel.product;
public class PlanItem extends PlanComponent {
public PlanItem(String name, String description) {
super(name, description);
}
public String getName() {
return name;
}
public String getDescription() {
return description;
}
public void print() {
System.out.println("\t" + getName() + "\n");
System.out.println("\t\t" + getDescription() + "\n");
}
}
1.4.2.2. nijel.builder ¶
// director
package nijel.builder;
import nijel.product.PlanComponent;
public abstract class Planner {
abstract public PlanComponent makePlan();
}
// concrete director
package nijel.builder;
import nijel.product.PlanComponent;
public class MyPlanner extends Planner {
private Builder builder;
public MyPlanner(Builder builder) {
this.builder = builder;
}
public PlanComponent makePlan() {
int first, second, third;
first = 1;
builder.buildDay(first);
builder.addHotel(first, "Patternsland 5 star Hotel");
builder.addTickets(first, "Park Ticket: R");
builder.addReservation(first, "Dinner at VERY expensive French restaurant");
second = 2;
builder.buildDay(second);
builder.addHotel(second, "Maybe Hotel");
builder.addTickets(second, "Park Ticket: A");
builder.addSpecialEvent(second, "Patterns on Ice");
builder.addReservation(second, "just dinner");
third = 3;
builder.buildDay(third);
builder.addHotel(third, "Wannabe Hotel");
builder.addTickets(third, "Ticket for Children!");
return builder.getVacationPlan();
}
}
// builder
package nijel.builder;
import nijel.product.PlanComponent;
public interface Builder {
abstract public void buildDay(int date);
abstract public void addHotel(int date, String hotel);
abstract public void addTickets(int date, String ticket);
abstract public void addSpecialEvent(int date, String event);
abstract public void addReservation(int date, String restaurant);
abstract public PlanComponent getVacationPlan();
}
// concrete builder
package nijel.builder;
import nijel.product.Plan;
import nijel.product.PlanComponent;
import nijel.product.PlanItem;
public class VacationBuilder implements Builder {
private PlanComponent plan;
public VacationBuilder(String description) {
plan = new Plan(description);
}
public void addHotel(int date, String hotel) {
PlanComponent hotelReservation = new PlanItem(hotel);
plan.getChild(date - 1).add(hotelReservation);
}
public void addSpecialEvent(int date, String event) {
PlanComponent specialEvent = new Plan("Special Event");
specialEvent.add(new PlanItem(event));
plan.getChild(date - 1).add(specialEvent);
}
public void addTickets(int date, String ticket) {
PlanComponent admissionTicket = new PlanItem(ticket);
plan.getChild(date - 1).add(admissionTicket);
}
public void buildDay(int date) {
plan.add(new Plan(date + "day's plan"));
}
public PlanComponent getVacationPlan() {
return plan;
}
public void addReservation(int date, String restaurant) {
PlanComponent reservation = new Plan("Dining");
reservation.add(new PlanItem(restaurant));
plan.getChild(date - 1).add(reservation);
}
}
1.4.2.3. nijel.client ¶
package nijel.client;
import nijel.builder.*;
import nijel.product.*;
public class Client {
public static void main(String[] args) {
PlanComponent perfectVacationPlan;
Planner perfectPlanner =
new MyPlanner(new VacationBuilder("Perfect Vacation Plan"));
perfectVacationPlan = perfectPlanner.makePlan();
perfectVacationPlan.print();
}
}
1.5. Builder Pattern ê³¼ Abstract Factory Pattern ì�˜ ì°¨ì�´ì � ¶
보시다 시피 Builder Pattern ê³¼ Abstract Factory Pattern ì�€ ë§Žì�´ 비슷하다. ì°¨ì�´ì �ì�´ë�¼ë©´ 약간 ë¯¸ë¬˜í•˜ë‹¤ê³ ë�„ í• ìˆ˜ 있는ë�°, Abstract Factory Pattern ì�€ 무엇ì�´ 만들어지는가 ì—� ì´ˆì �ì�„ ë§žì¶”ê³ ìžˆê³ , Builder Pattern ì�€ 어떻게 만들어 지는가ì—� ì´ˆì �ì�„ ë§žì¶”ê³ ìžˆë‹¤ê³ í’€ì�´í• 수 있다. ë¬¼ë¡ ë‘� 종류ì�˜ Creational Pattern ì�€ Product ì�„ ì œê³µí•˜ëŠ”ë�° 첫번째 ì±…ìž„ì�´ 존재한다. 가장 í�° ì°¨ì�´ì �ì�´ë�¼ë©´, Builder Pattern ì�€ 복잡한 오브ì �트를 한단계 한단계 만들어서 최종 단계ì—� ë¦¬í„´í•´ì£¼ê³ , Abstract Factory Pattern ì�€ 여러 종류ì�˜ generic 한 product 를 여러종류ì�˜ concrete factory ê°€ ìƒ�성하기 때문ì—� ê°�ê°�ì�˜ 오브ì �트가 만들어질 때마다 product 를 ë°›ì�„ 수 있게 ë�œë‹¤.
Abstract Factory Pattern : ì–´ë–¤ 종류ì�˜ 명확한 오브ì �트를 ìƒ�ì„±í• ê²ƒì�¸ì§€ë¥¼ 실행 시간까지 연기한다. (실행시간ì—� ê²°ì •í•œë‹¤) 예를 들ìž�ë©´, ë ˆìŠ¤í† ëž‘ì—�서 오늘ì�˜ 추천메뉴를 ì„ íƒ�하는 것ì�´ë‹¤. 서버(interface to factory)는 "오늘ì�˜ 추천요리" ë�¼ëŠ” abstract generic message 를 주방(concrete factory)ì—� ì „ë‹¬í•˜ê³ ì�Œì‹�ì�„ 받게 ë� 때 concrete product 를 얻게 ë�˜ëŠ” 것ì�´ë‹¤.
Builder Pattern : 복잡한 오브ì �트를 ì–´ë–¤ ë°©ì‹�으로 조합하여 만들어낼지 ì—� 대한 방법ì�„ ì œê³µí•œë‹¤. (encapsulate) 예를 들ìž�ë©´, ê±´ì¶•ì—…ìž�와 계약ì�„ 해서 ì§‘ì�„ 건설 í• ë•Œ, ê±´ì¶•ì—…ìž�(builder) ì—�게 í�‰ë©´ë�„(product ì�˜ 윤곽)를 ì œê³µí•˜ë©´ ê±´ì¶•ì—…ìž�는 ì�¼ë ¨ì�˜ 작업ì�„ ê±°ì³�서 ì§‘(complex object)ì�„ 만들어 낸다.
ì—…ë�°ì�´íЏ ì˜ˆì •.
�문� http://en.wikipedia.org/wiki/Builder_pattern
�문� http://en.wikipedia.org/wiki/Builder_pattern












