본문 바로가기
CS note/디자인 패턴, 프로그래밍 패러다임

factory pattern (팩토리 패턴)

by 코드 이야기 2023. 1. 25.
728x90

 

factory pattern (팩토리 패턴) 

객체를 사용하는 코드에서 생성 부분을 떼어내 추상화한 패턴.

상속 관계에 있는 두 클래스에서 상위 클래스가 중요한 뼈대를 결정하고,
하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴.

 

장점

  • 낮은 결합도
    • 상위 클래스와 하위 클래스가 분리되므로 낮은 결합도를 가진다.
  • 확장성 및 유지보수성 증가
    • 객체 생성 로직이 분리되어 수정 시 한 곳만 수정할 수 있다.

 

 

 

예제 코드 (Kotlin)

fun main() {
val latte = CoffeeFactory.getCoffee("Latte", 4000)
val ame = CoffeeFactory.getCoffee("Americano", 3000)
val milk = CoffeeFactory.getCoffee("Milk", 2000)
println("Factory latte :: $latte")
println("Factory ame :: $ame")
println("Factory milk :: $milk")
}
// 상위 클래스로 중요한 뼈대를 설정
object CoffeeFactory {
fun getCoffee(type: String, price: Int): Coffee {
return when {
"Latte".equals(type, ignoreCase = true) -> Latte(price)
"Americano".equals(type, ignoreCase = true) -> Americano(price)
else -> DefaultCoffee()
// Enum, Map을 이용해 if문을 사용하지 않고 매핑할 수 있다.
}
}
}
abstract class Coffee {
abstract val price: Int
override fun toString(): String {
return "This coffee is $price"
}
}
class Latte(override val price: Int): Coffee()
class Americano(override val price: Int): Coffee()
class DefaultCoffee: Coffee() {
override val price: Int
init {
price = -1
}
}
/*
Factory latte :: This coffee is 4000
Factory ame :: This coffee is 3000
Factory milk :: This coffee is -1
*/

* String의 equals 옵션 ignoreCase : true로 설정할 시 문자열의 대소문자를 구분하지 않고 비교한다.

* abstract class (추상 클래스) : 미완성 클래스, 이 자체로 인스턴스화될 수 없는 클래스.

* abstract : 상속을 받는 곳에서 구현을 강제시키는 키워드

  (위 코드에서 price 변수에 abstract 키워드가 사용되어 DefaltCoffee class에서 price 변수의 값을 필수로 초기화해야 한다.)

 

 

 

fun main() {
var gs: GameServer
gs = GameServerFactory.KRGameServer
gs.execute("supermario")
println()
gs = GameServerFactory.JPGameServer
gs.execute("tetris")
}
object GameServerFactory {
val KRGameServer = KRGameServer()
val JPGameServer = JPGameServer()
}
abstract class GameServer {
protected abstract fun chooseGame(game: String): Games
fun GameServer() = println("연결 성공")
fun execute(game: String) {
val games: Games = chooseGame(game)
games.bootUpGame()
games.runGame()
}
}
abstract class Games {
abstract val title: String
abstract val version: String
fun bootUpGame() {
println("게임: $title")
println("버전: $version")
println("$title 게임 준비 완료")
}
fun runGame() = println("$title 게임 시작")
}
class KRGameServer : GameServer() {
private val supermario: Games = KRSuperMario()
private val tetris: Games = KRTetris()
override fun chooseGame(game: String): Games {
return when (game) {
"tetris" -> tetris
"supermario" -> supermario
else -> throw IllegalArgumentException("지원되지 않는 게임입니다.")
}
}
}
class JPGameServer : GameServer() {
private val supermario: Games = JPSuperMario()
private val tetris: Games = JPTetris()
override fun chooseGame(game: String): Games {
return when (game) {
"tetris" -> tetris
"supermario" -> supermario
else -> throw IllegalArgumentException("지원되지 않는 게임입니다.")
}
}
}
class KRSuperMario(
override val title: String = "수퍼마뤼오",
override val version: String = "1.0.4"
) : Games()
class KRTetris(
override val title: String = "테투리수",
override val version: String = "1.0.5"
) : Games()
class JPSuperMario(
override val title: String = "スーーパーーマリオ",
override val version: String = "1.0.6"
) : Games()
class JPTetris(
override val title: String = "テトリスですよー!",
override val version: String = "1.0.7"
) : Games()
/*
게임: 수퍼마뤼오
버전: 1.0.4
수퍼마뤼오 게임 준비 완료
수퍼마뤼오 게임 시작
게임: テトリスですよー!
버전: 1.0.7
テトリスですよー! 게임 준비 완료
テトリスですよー! 게임 시작
*/

 

 

 

 

 


참고

 

 


필자의 보완점

 

  • Factory Method (팩토리 메서드), Abstract Factory (추상 팩토리) 등이 있는 것 같으나 어떤 차이인지 잘 모르겠다.

 

 

 

728x90

댓글