U E D R , A S I H C RSS

니젤프림/Builder Pattern

1. Builder Pattern


빌� 패턴� 소프트웨어 디�� 패턴� 하나�다. 빌� 패턴� 복잡한 �체를 �성하는 방법과, 표현하는 방법� 정�하는 �래스를 별�로 분리한다. � 분리로서 얻어지는 효과는, ��한 �성 과정� 다른 표현� 얻어낼 수 있게 �는 것�다.

쉽게 �해서, 아주 복잡한 오브�트를 �성해야하는�, 그 �� 오브�트를 �하는 �래스가 하는게 아니�, Builder �게 시키는 것�다. 그런� �꾸 나오는 �성/표현 � �미는, 바로 director � 존재를 설명해 준다고 할 수 있다. director 는 Building step(construction process) � 정�하고 concrete builder 는 product � 구체�� 표현(representation) � 정�하기�.. 그리고, builder 가 추��� �터페�스를 제공하므로 director 는 그것� �용하는 것�다.

1.1. 언제 쓰나?

복잡한 ��터구조를 �성해야 할 때. 너무 간단한가?

1.2. 실�활� �용�는 쉬운 예

패스트(정�)푸드 레스토랑 맥�날드�서 어린�용 해피밀� 만들어내는 걸로 예를 들 수 있다. �반�으로 해피밀� 메�, 사�드, �료, 장난� (햄버거, 프��, 콜�, 매달 바뀌는 장난�)으로 �루어져 있다. 여기서 중요한건, �런 템플릿� 정해져 있다는 것�다. 요즘 같� 까다로운 아�들�게 어릴때부터 맥�날드� 입맛� 확실히 들여놓으려면 당연히 다양한 바리��션� 필요하다. 고�� 햄버거나 치즈버거나, 아니면 맥너겟�나 �런걸 선�할 수 있지만, 기본�으로 해피밀� 구성�는 방��는 변함 없다. 여기서 빌� 패턴� �용한다면, 카운터�서 주문� 받는 ��� Director �고 할 수 있다. 물론 고�� Customer �다. 고�� �하는 바리��션� 선�해서 해피밀 셋트를 구성하게 �면 (Customer가 Concrete Builder 를 선�한다) Director 는 정해진 템플릿� 따� 주방 ��(Concrete Builder) �게 �뢰하여 해피밀 세트(Product) 를 만들어 낸다. 여기서 Director 가 Concrete Builder �게 요구하는 방�� 종류� 따� 비슷 하므로 그것� 추�화시킨 �터페�스를 Builder �고 할 수 있겠다.



1.3.1. Builder

Product 를 �성하는 템플릿. Abstract Interface �고� 할 수 있다.

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.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
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:28:55
Processing time 0.0096 sec