๋ฌธ์ ์ ๋ํ ์ค๋ช
์
๋๋ค.
์ฐ๋ฆฌ๋ ํ๋ก๊ทธ๋จ์ ์์ฑํด์ผ ํฉ๋๋ค. ์นํจ, ์๋ฉ๋ฆฌ์นธ, ๋ฏธํธ, ํ์์ด์, ํํผ๋ก๋ ๋ฑ ๋ค์ํ ์ข
๋ฅ์ ํผ์๋ฅผ ์ค๋นํ๋ ค๋ ํผ์ ๊ฐ๊ฒ์ ๊ฒฝ์ฐ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์ ํฉํ ํ
ํ๋ฆฟ๊ณผ ์๋๋ฆฌ์ค๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ ํต์ ์ผ๋ก Builder ํ
ํ๋ฆฟ์ "ํผ์ ๋ฌธ์ "๋ฅผ ํด๊ฒฐํ๋ ๋ฐ ์ฌ์ฉ๋์์ต๋๋ค. Decorator ํจํด์ ์ฌ์ฉํ ์๋ ์๋๋ฐ, ๋ ํจํด ๋ชจ๋ ๋ง์ง๋ง ์ฌ์ฉ๋ฒ์๋ ์ฐจ์ด๊ฐ ์์ต๋๋ค. Builder๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ํ ํ
ํ๋ฆฟ์ธ ๋ฐ๋ฉด, Decorator๋ ์์ฑ๋ ๊ฐ์ฒด๋ฅผ ์ฆ์ ์์ ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด ์ด๊ฒ์ ์ดํดํด ๋ด
์๋ค:
1. ํ
ํ๋ฆฟ ๋น๋:
์ด ๊ฒฝ์ฐ ํผ์๋ ๋ชจ๋ ์ฌ๋ฃ๋ฅผ ํ ๋ฒ์ ์ค๋น๋ฉ๋๋ค.
ํผ์ ์์
:
public class Pizza{ private float totalPrice = 0; private Size size; private Topping topping; private Crust crust; private Cheese cheese; public Size getSize(){ return size; } public void setSize(Size size){ this.size = size; } public Topping getTopping(){ return topping; } public void setTopping(Topping topping){ this.topping = topping; } public Crust getCrust(){ return crust; } public void setCrust(Crust crust){ this.crust = crust; } public Cheese getCheese(){ return cheese; } public void setCheese(Cheese cheese){ this.cheese = cheese; } public float getTotalPrice(){ return totalPrice; } public void addToPrice(float price){ this.totalPrice = totalPrice + price; } }
4๊ฐ์ ์ด๊ฑฐํ ํด๋์ค:
public enum Cheese { AMERICAN{ public float getCost(){ return 40; } }, ITALIAN { public float getCost(){ return 60; } }; public abstract float getCost(); } public enum Crust { THIN{ public float getCost(){ return 70; } } , STUFFED{ public float getCost(){ return 90; } }; public abstract float getCost(); } public enum Size { MEDIUM { public float getCost() { return 100; } }, LARGE { public float getCost() { return 160; } }; public abstract float getCost(); } public enum Topping { PEPPERONI { public float getCost(){ return 30; } }, CHICKEN{ public float getCost(){ return 35; } }, MUSHROOM{ public float getCost(){ return 20; } }; public abstract float getCost(); }
PizzaBuilder ํด๋์ค:
public class PizzaBuilder { Pizza pizza = new Pizza(); public PizzaBuilder withTopping(Topping topping) { pizza.setTopping(topping); pizza.addToPrice(topping.getCost()); return this; } public PizzaBuilder withSize(Size size) { pizza.setSize(size); pizza.addToPrice(size.getCost()); return this; } public PizzaBuilder withCrust(Crust crust) { pizza.setCrust(crust); pizza.addToPrice(crust.getCost()); return this; } public Pizza build() { return pizza; } public double calculatePrice() { return pizza.getTotalPrice(); } }
์์
ํ
์คํธ:
public class PizzaBuilderTest { @Test public void shouldBuildThinCrustChickenPizza(){ Pizza pizza = new PizzaBuilder().withCrust(Crust.THIN).withTopping(Topping.CHICKEN).withSize(Size.LARGE).build(); assertEquals(Topping.CHICKEN,pizza.getTopping()); assertEquals(Size.LARGE,pizza.getSize()); assertEquals(Crust.THIN,pizza.getCrust()); assertEquals(265.0,pizza.getTotalPrice(),0); } }
2. ๋ฐ์ฝ๋ ์ดํฐ ํ
ํ๋ฆฟ:
๋ฐ์ฝ๋ ์ดํฐ ํจํด์ ์๋ณธ ๊ฐ์ฒด์ ์ํฅ์ ์ฃผ์ง ์๊ณ ๋์ ์ผ๋ก ๊ฐ์ฒด์ ์ถ๊ฐ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ฑฐ๋ ์ ๊ฑฐํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ํผ์ ๋ฒ ์ด์ค๋ฅผ ๋จผ์ ๋ง๋ ํ ๋ค์ํ ์ฌ๋ฃ๋ฅผ ์ถ๊ฐํ ๋ ์ฌ์ฉํฉ๋๋ค. ์ฌ๊ธฐ์๋ ์ฅ์ํ๋ ค๋ BasePizza(๊ธฐ๋ณธ ๊ตฌ์ฑ ์์)์ ๋ํ ์ธํฐํ์ด์ค(Pizza)์ ์ค์ ๋ก ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ PizzaDecorator ํด๋์ค๊ฐ ํ์ํฉ๋๋ค.
ํผ์ ์ธํฐํ์ด์ค:
public interface Pizza { public String bakePizza(); public float getCost(); }
BasePizza ๊ตฌํ:
public class BasePizza implements Pizza{ public String bakePizza() { return "Basic Pizza"; } public float getCost(){ return 100; } }
PizzaDecorator ํด๋์ค:
public class PizzaDecorator implements Pizza { Pizza pizza; public PizzaDecorator(Pizza newPizza) { this.pizza = newPizza; } public String bakePizza() { return pizza.bakePizza(); } @Override public float getCost() { return pizza.getCost(); } }
๋ฐ์ฝ๋ ์ดํฐ 2๊ฐ: ๋ฒ์ฏ๊ณผ ํํผ๋ก๋
public class Mushroom extends PizzaDecorator { public Mushroom(Pizza newPizza) { super(newPizza); } @Override public String bakePizza() { return super.bakePizza() + " with Mushroom Topings"; } @Override public float getCost() { return super.getCost()+80; } }
public class Pepperoni extends PizzaDecorator { public Pepperoni(Pizza newPizza) { super(newPizza); } @Override public String bakePizza() { return super.bakePizza() + " with Pepperoni Toppings"; } @Override public float getCost() { return super.getCost()+110; } }
์์
ํ
์คํธ:
public class PizzaDecoratorTest { @Test public void shouldMakePepperoniPizza(){ Pizza pizza = new Pepperoni(new BasePizza()); assertEquals("Basic Pizza with Pepperoni Toppings",pizza.bakePizza()); assertEquals(210.0,pizza.getCost(),0); } }
์ฐจ์ด์
Builder ๋ฐ Factory(๋ฐ Abstract Factory)์ ๊ฐ์ ํจํด์ ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ Decorator(๊ตฌ์กฐ์ ๋์์ธ ํจํด์ด๋ผ๊ณ ๋ ํจ)์ ๊ฐ์ ํจํด์ ํ์ฅ์ฑ์ ์ํด ์ฌ์ฉ๋๊ฑฐ๋ ์ด๋ฏธ ์์ฑ๋ ๊ฐ์ฒด์ ๊ตฌ์กฐ์ ๋ณ๊ฒฝ์ ์ ๊ณตํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๋ ๊ฐ์ง ์ ํ์ ํจํด ๋ชจ๋ ์ฃผ๋ก ์์์ ํตํด ๊ตฌ์ฑ์ ์ด์งํ๋ฉฐ, ๋ฐ์ฝ๋ ์ดํฐ ๋์ ๋น๋๋ฅผ ์ฌ์ฉํ ๋งํผ ์ฐจ์ด์ ์ด ํฌ์ง ์์ต๋๋ค. ๋ ๋ค ์คํํ ๋ ์์๋ฐ์ง ์๊ณ ์์ฒด ๋์์ ์ ๊ณตํฉ๋๋ค. ์ด๋ค ๊ฒฝ์ฐ์๋ ๋น๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข์ต๋๋ค - ํน์ ์์ฑ/๊ธฐ๋ฅ์ ๊ฐ์ง ๊ฐ์ฒด ์์ฑ์ ์ ํํ๋ ค๋ ๊ฒฝ์ฐ. ์๋ฅผ ๋ค์ด, ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ ์ ์ค์ ํด์ผ ํ๋ ์์ฑ์ด 4~5๊ฐ ์๊ฑฐ๋ ํน์ ์์ฑ์ด ์์ง ์ค์ ๋ ๋๊น์ง ๊ฐ์ฒด ์์ฑ์ ๋๊ฒฐํ๋ ค๊ณ ํฉ๋๋ค. ๊ฐ๋จํ ๋งํด์ Joshua Bloch๊ฐ Java: Effective Programming, 2nd ed์์ ์ด ๊ฒ์ฒ๋ผ ์์ฑ์ ๋์ ์ฌ์ฉํ์ธ์. ๋น๋๋ ์์ฑ๋ ๊ฐ์ฒด์ ์์ด์ผ ํ๋ ์์ฑ์ ์ ๊ณตํ์ง๋ง ์์ฑ์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ์จ๊น๋๋ค. ๋ฐ์ฝ๋ ์ดํฐ๋ ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋ ๊ธฐ์กด ๊ฐ์ฒด์ ์ ์์ฑ์ ์ถ๊ฐํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๋ชจ๋ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋๋ ๋์ ๊ฐ์ฒด๋ฅผ ๊ณ ์ ํ๋ ๋ฐ์๋ ์ ํ์ด ์์ต๋๋ค. ๋ ํ
ํ๋ฆฟ ๋ชจ๋ ๊ตฌ์ฑ์ ์ฌ์ฉํ๋ฉฐ ๋น์ทํด ๋ณด์ผ ์ ์์ต๋๋ค. ์ฃผ์ ์ฐจ์ด์ ์ ์ฌ์ฉ์ ์์ต๋๋ค.
GO TO FULL VERSION