디자인 패턴 - 생성패턴

kimbbang·2021년 9월 16일
0

디자인 패턴을 크게 나누면 생성패턴, 구성패턴, 행위패턴으로 나눌 수 있다.

생성패턴은 총 5가지의 패턴으로 구성되어 있다.

5가지 생성패턴

팩토리 메서드 패턴
추상 팩토리 패턴
빌더 패턴
프로토타입
싱글톤

위의 5가지 패턴은 다시 클래스 생성패턴과 객체 생성패턴으로 나눌 수 있다.

클래스 생성패턴에 해당하는 팩토리 메서드 패턴을 제외한 나머지 패턴들은 객체 생성패턴에 해당한다.

토비 스프링 1장에서는 팩토리 메서드 패턴과 추상 팩토리 패턴이 다뤄졌고, 아직 다뤄지지 않은 생성패턴 중 빌더 패턴에 대해 알아보았다.

빌더패턴

객체를 생성하는 방법과 표현하는 방법을 정의하는 클래스를 별도로 분리하여 서로 다른 표현이라도 이를 생성할 수 있는 동일한 절차를 제공하는 패턴이라고 한다.

인스턴스를 빌더라는 내부 클래스를 통해 간접적으로 생성하게 한다.

Builder : 빌더 인터페이스
ConcreteBuilder : 빌더 인터페이스 구현체
Director : Builder를 사용해 객체를 생성
Product : Director가 Builder로 만들어낸 결과물

builder가 부품을 만들고, director는 builder가 만든 부품을 조합하여 결과물을 만든다.

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 Cook {
	private PizzaBuilder pizzaBuilder;

	public void setPizzaBuilder(PizzaBuilder pizzaBuilder) {
		this.pizzaBuilder = pizzaBuilder;
	}

	public Pizza getPizza() {
		return pizzaBuilder.getPizza();
	}

	public void constructPizza() {
		pizzaBuilder.createNewPizzaProduct();
		pizzaBuilder.buildDough();
		pizzaBuilder.buildSauce();
		pizzaBuilder.buildTopping();
	}
}

/** A given type of pizza being constructed. */
public class BuilderExample {
	public static void main(String[] args) {
		Cook cook = new Cook();
		PizzaBuilder hawaiianPizzaBuilder = new HawaiianPizzaBuilder();
		PizzaBuilder spicyPizzaBuilder = new SpicyPizzaBuilder();

		cook.setPizzaBuilder(hawaiianPizzaBuilder);
		cook.constructPizza();

		Pizza pizza = cook.getPizza();
	}
}

빌더 패턴의 장점

디자인적으로 유연하고 읽기 가독성 높은 코드가 된다.

생성자의 매개변수가 줄어들고 생성자의 파라미터가 가독성 높은 메서드 호출로 제공된다. 인스턴스를 생성하는 동안 생성자에 선택적 파라미터인 null을 넘길 필요가 없다.

개발자가 필드 설정을 위해 적절한 setter를 호출하지 않아도 완전한 상태로 인스턴스가 생성된다.

빌더 패턴의 단점

setter 메서드의 필요성을 제거하여 일부 코드 줄 수를 줄이지만, builder 객체를 도입함으로써 대략 두 배로 코드 줄 수를 늘린다.

클라이언트 코드의 가독성이 우수해지는 만큼 장황해진다.

출처

빌더 패턴 (wikipedia)
builder-pattern-in-java
gof - 디자인 패턴의 빌더 패턴

0개의 댓글