디자인패턴
Abstract Factory Pattern
hik14
2022. 8. 1. 15:56
추상 팩토리 패턴
특정한 제품군을 생성할때 사용한다.
구상 클래스에 의존하지 않고도 서로 연관되거나 의존적인 객체로 이루어진 제품군을 생산하는 인터페이스를 제공합니다.
추상 팩토리 인터페스 및 구상 클래스.
interface PizzaIngredientFactory {
fun createDough(): Dough
fun createSauce(): Sauce
fun createCheese(): Cheese
fun createPepperoni(): Pepperoni
}
class NYPizzaIngredientFactory : PizzaIngredientFactory {
override fun createDough(): Dough = ThinCrustDough()
override fun createSauce(): Sauce = MarinaraSauce()
override fun createCheese(): Cheese = ReggianoCheese()
override fun createPepperoni(): Pepperoni = ThickPepperoni()
}
class ChicagoPizzaIngredientFactory : PizzaIngredientFactory {
override fun createDough(): Dough = ThickCrustDough()
override fun createSauce(): Sauce = PlumTomatoSauce()
override fun createCheese(): Cheese = MozzarellaCheese()
override fun createPepperoni(): Pepperoni = SlicedPepperoni()
}
원재료 인터페이스 및 클래스
interface Dough
class ThickCrustDough : Dough {
init {
println("두꺼운 크러스트 도우")
}
}
class ThinCrustDough : Dough {
init {
println("얇은 크러스트 도우")
}
}
interface Sauce
class PlumTomatoSauce : Sauce {
init {
println("플럼 토마토 소스")
}
}
class MarinaraSauce : Sauce {
init {
println("마리아라 소스")
}
}
interface Cheese
class MozzarellaCheese : Cheese {
init {
println("모짜랄레 치즈")
}
}
class ReggianoCheese : Cheese {
init {
println("레기아노치즈")
}
}
interface Pepperoni
class SlicedPepperoni : Pepperoni {
init {
println("얇게 썰린 페퍼로니")
}
}
class ThickPepperoni : Pepperoni {
init {
println("통 페퍼로니")
}
}
기존의 클래스들 prepare()를 추상클래스로 변경한다.
각 피자에 맞도록 제품군을 원재료 클래스에서 생성한다.
enum class PizzaType {
CHEESE, PEPPERONI
}
abstract class Pizza(val ingredientFactory: PizzaIngredientFactory) {
abstract val name: String
lateinit var dough: Dough
lateinit var sauce: Sauce
lateinit var cheese: Cheese
lateinit var pepperoni: Pepperoni
abstract fun prepare()
fun bake() {
println("175도에서 25분간 굽기")
}
open fun cut() {
println("피자를 사선으로 자르기")
}
fun box() {
println("상자에 피자 담기")
}
}
class NYStyleCheesePizza(ingredientFactory: PizzaIngredientFactory) : Pizza(ingredientFactory) {
override val name: String = "뉴욕 스타일 치즈 피자"
override fun prepare() {
println("준비중: $name")
dough = ingredientFactory.createDough()
sauce = ingredientFactory.createSauce()
cheese = ingredientFactory.createCheese()
}
}
class NYStylePepperoniPizza(ingredientFactory: PizzaIngredientFactory) : Pizza(ingredientFactory) {
override val name: String = "뉴욕 스타일 페퍼로니 피자"
override fun prepare() {
println("준비중: $name")
dough = ingredientFactory.createDough()
sauce = ingredientFactory.createSauce()
pepperoni = ingredientFactory.createPepperoni()
}
}
class ChicagoStyleCheesePizza(ingredientFactory: PizzaIngredientFactory) : Pizza(ingredientFactory) {
override val name: String = "시카고 스타일 치즈 피자"
override fun cut() {
println("네모난 모양으로 피자 자르기")
}
override fun prepare() {
println("준비중: $name")
dough = ingredientFactory.createDough()
sauce = ingredientFactory.createSauce()
cheese = ingredientFactory.createCheese()
}
}
class ChicagoStylePepperoniPizza(ingredientFactory: PizzaIngredientFactory) : Pizza(ingredientFactory) {
override val name: String = "시카고 스타일 페퍼로니 피자"
override fun cut() {
println("네모난 모양으로 피자 자르기")
}
override fun prepare() {
println("준비중: $name")
dough = ingredientFactory.createDough()
sauce = ingredientFactory.createSauce()
pepperoni = ingredientFactory.createPepperoni()
}
}
abstract class PizzaStore {
// 어떤 피자던 주문하는 과정 및 포장 처리는 변함이 없다.
fun orderPizza(type: PizzaType): Pizza {
val pizza = createPizza(type)
pizza.prepare()
pizza.bake()
pizza.cut()
pizza.box()
return pizza
}
// 피자의 종류에 따라 실제 어떤 피자를 생성하여 반환 할지는 하위 클래스에서 결정하기로 한다.
protected abstract fun createPizza(type: PizzaType): Pizza
}
class NYPizzaStore : PizzaStore() {
override fun createPizza(type: PizzaType): Pizza {
val ingredientFactory = NYPizzaIngredientFactory()
return when (type) {
PizzaType.CHEESE -> {
NYStyleCheesePizza(ingredientFactory)
}
PizzaType.PEPPERONI -> {
NYStylePepperoniPizza(ingredientFactory)
}
}
}
}
class ChicagoPizzaStore : PizzaStore() {
override fun createPizza(type: PizzaType): Pizza {
val ingredientFactory = ChicagoPizzaIngredientFactory()
return when (type) {
PizzaType.CHEESE -> {
ChicagoStyleCheesePizza(ingredientFactory)
}
PizzaType.PEPPERONI -> {
ChicagoStylePepperoniPizza(ingredientFactory)
}
}
}
}
fun main() {
val nyStore: PizzaStore = NYPizzaStore()
nyStore.orderPizza(PizzaType.CHEESE)
println("------------------------------------------------------")
val chicagoStore: PizzaStore = ChicagoPizzaStore()
chicagoStore.orderPizza(PizzaType.PEPPERONI)
}
실행 결과