소프트웨어 개발 시 객체 생성 로직은 복잡해지기 쉽다.
직접 'new' 키워드로 생성하면 간단하지만, 1) 객체 생성 방식이 복잡하거나, 2) 상황에 따라 다른 하위 클래스 객체를 반환하려면 객체 생성 책임을 분리하는 패턴이 필요하다.
이때 대표적인 디자인 패턴이 바로 Factory 패턴 계열이다.

Factory 패턴
Factory 패턴은 객체 생성 로직을 별도의 Factory class-method로 캡슐화한다. 클라이언트는 구체적인 클래스 이름을 알 필요 없이, Factory를 통해 객체를 얻을 수 있다.
하지만 흔히 Factory 패턴이라고 뭉뚱그리다 보니, Simple Factory / Factory Method / Abstract Factory의 차이를 헷갈리기 쉽다.
이번 글에서는 Kotlin으로 위 세 가지를 직접 구현하면서 차이를 정리하고자 한다.
Simple Factory (정적 팩토리)
GoF 『Design Patterns』에 나오지 않는 관용적 방식으로, 객체 생성을 전담하는 클래스를 두고, 조건문으로 분기해 객체를 반환하는 방법이다.
package org.example.factory
// Factory
object ShapeFactory {
fun createShape(type: String): Shape? {
return when (type.lowercase()) {
"circle" -> Circle()
"square" -> Square()
else -> null
}
}
}
// Product (인터페이스)
interface Shape {
fun draw()
}
// Concrete Products
class Circle : Shape {
override fun draw() = println("Circle")
}
class Square : Shape {
override fun draw() = println("Square")
}
fun main() {
val circle = ShapeFactory.createShape("circle")
circle?.draw()
val square = ShapeFactory.createShape("square")
square?.draw()
}
특징
- 클라이언트는 'new' 대신 'Factory'를 호출한다.
- 생성 로직이 Factory 내부에 존재한다.
- 확장성은 부족하다. (case가 많아질 수록 when 조건문이 커짐)
- GoF의 정식 패턴은 아니지만, 가장 널리 사용된다.
> 코드 내 'circle'이나 'square' 같은 값들이 실제로 코드에 존재할지를 보장하지 않는다.
(주로 DB에 있는 값을 불러오기 때문에)
Factory Method
GoF가 정의한 정식 패턴으로, 객체 생성 메서드의 인터페이스만 정의하고, 구체적인 생성 로직은 서브 클래스에 위임한다.
package org.example.factory
// Creator (Factory Method 보유)
abstract class Dialog {
abstract fun createButton(): Button
fun renderDialog() {
val button = createButton()
println("Rendering Common Dialog..")
button.render()
}
}
// Concrete Creators
class WindowsDialog : Dialog() {
override fun createButton(): Button = WindowsButton()
}
class MacDialog : Dialog() {
override fun createButton(): Button = MacButton()
}
// Product
interface Button {
fun render()
}
// Concrete Products
class WindowsButton : Button {
override fun render() = println("Rendering Windows Button")
}
class MacButton : Button {
override fun render() = println("Rendering Mac Button")
}
// Client
fun main() {
val os = System.getProperty("os.name").lowercase()
val dialog: Dialog = if("win" in os) WindowsDialog() else MacDialog()
dialog.renderDialog()
}
특징
- 객체 생성 책임이 서브클래스로 분리된다.
- 새로운 Product를 추가하려면 Creator를 확장하면 된다.
- Template Method 패턴과 유사한 구조를 띈다.
Abstract Factory
GoF가 정의한 정식 패턴. 관련 객체(제품군)를 통일된 방식으로 묶어서 생성 가능한 방식이다.
"Windows-styled UI", "Mac-styled UI" 처럼 세트로 객체를 작성해야 할 때 유용하다.
package org.example.factory
// Abstract Factory
interface GUIFactory {
fun createButton() : Button
fun createCheckbox() : Checkbox
}
// Concrete Factories
class WinFactory : GUIFactory {
override fun createButton() : Button = WindButton()
override fun createCheckbox(): Checkbox = WinCheckbox()
}
class MacFactory : GUIFactory {
override fun createButton() : Button = MacButton()
override fun createCheckbox(): Checkbox = MacCheckbox()
}
// Abstract Products
interface Button {
fun render()
}
interface Checkbox {
fun check()
}
// Concrete Products
class WindButton : Button {
override fun render() = println("Windows Button")
}
class WinCheckbox : Checkbox {
override fun check() = println("Windows Checkbox")
}
class MacButton : Button {
override fun render() = println("Mac Button")
}
class MacCheckbox : Checkbox {
override fun check() = println("Mac Checkbox")
}
// Client
fun main() {
val os = System.getProperty("os.name").lowercase()
val factory: GUIFactory = if ("win" in os) WinFactory() else MacFactory()
val button = factory.createButton()
val checkbox = factory.createCheckbox()
button.render()
checkbox.check()
}
특징
- 제품군 전체를 생성한다.
- "호환성"을 보장한다. (Windows Factory -> Windows UI set)
- 새로운 제품군을 추가하기 쉽지만, 기존 제품군에 새로운 타입(Product)를 추가하려면 코드 수정이 필요하다.
정리
Factory Method vs. Abstract Factory
Factory Method
- 목적 : "객체 생성 책임을 서브클래스에게 위임"
- 요점 : 하나의 제품(Product) 계열 생성에 집중 (ButtonFactory > WindowsButton, MacButton)
Abstract Factory
- 목적 : "관련된 객체들의 집합을 생성하는 책임을 캡슐화"
- 요점 : 서로 관련 있는 여러 제품을 일관된 방식으로 생성 (UIFactory > WindowsUI : Button + Checkbox)
참고 자료
- https://4z7l.github.io/2020/12/25/design_pattern_GoF.html
- https://jusungpark.tistory.com/14
-
Powered By. ChatGPT
'Backend' 카테고리의 다른 글
| [Backend] Singleton 패턴 (1) | 2025.09.03 |
|---|---|
| [Backend] Bulider 패턴 (1) | 2025.09.03 |
| [Backend] 객체지향 디자인 패턴 (1) | 2025.09.03 |
| [Backend] Git & GitHub 소개 (0) | 2025.09.02 |
| [Backend] Kotlin 소개 (w. JVM) (1) | 2025.09.02 |