Menu
Coddy logo textTech

팩토리 패턴

Coddy Swift 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 57개 중 43번째.

팩토리 패턴은 객체 생성을 한곳에 모읍니다. 호출자는 필요한 것을 보통 이름이나 타입으로 요청하고, 어떤 구체 타입이 생성되었는지 알 필요 없이 바로 사용할 수 있는 객체를 받습니다:

protocol Shape { func area() -> Double }
struct Square: Shape { let side: Double; func area() -> Double { side * side } }
struct Circle: Shape { let r: Double; func area() -> Double { 3 * r * r } }

enum ShapeFactory {
    static func make(_ kind: String, size: Double) -> (any Shape)? {
        switch kind {
        case "square": return Square(side: size)
        case "circle": return Circle(r: size)
        default: return nil
        }
    }
}

print(ShapeFactory.make("square", size: 3)!.area())
print(ShapeFactory.make("hexagon", size: 3) == nil)

출력:

9.0
true

호출자는 프로토콜에만 의존합니다. 새로운 셰이프를 추가한다는 것은 셰이프를 생성하는 모든 곳이 아니라 팩토리를 변경한다는 의미입니다:

protocol Notifier { func send(_ m: String) -> String }
struct Email: Notifier { func send(_ m: String) -> String { "email: \(m)" } }
struct SMS: Notifier { func send(_ m: String) -> String { "sms: \(m)" } }

func makeNotifier(for user: String) -> any Notifier {
    user.hasSuffix("@mail.com") ? Email() : SMS()
}

print(makeNotifier(for: "ada@mail.com").send("hi"))
print(makeNotifier(for: "555-0100").send("hi"))

출력:

email: hi
sms: hi

타입 자체의 정적 팩토리 메서드는 이 패턴을 더 간단하게 구현한 형태입니다. 값를 생성하는 일반적인 방법에 이름을 부여합니다:

struct Color {
    let r: Int, g: Int, b: Int
    static func gray(_ v: Int) -> Color { Color(r: v, g: v, b: v) }
    static let white = Color(r: 255, g: 255, b: 255)
}

print(Color.gray(100).g)
print(Color.white.b)

출력:

100
255

ShapeFactory와 같이 케이스가 없는 열거형은 팩토리 함수를 그룹화하는 일반적인 방법입니다. 인스턴스화할 수 없으므로 순수하게 네임스페이스로 작동합니다.

enum ShapeFactory {        // 케이스 없음: 생성할 수 없음
    static func make(_ kind: String, size: Double) -> (any Shape)? { ... }
}
challenge icon

챌린지

쉬움

가격 플랜을 위한 팩토리를 작성하세요. Plan 프로토콜에는 name과 price(forUsers:) -> Int가 있습니다. Free(0, 단 3명 이하의 사용자만 가능하며 그 이상이면 허용되지 않음을 의미하는 -1을 가격으로 반환), Team(사용자당 10), Enterprise(고정 요금 500에 100명을 초과하는 사용자당 5 추가)를 구현하세요. free, team 또는 enterprise에 해당하는 플랜을 반환하고 그 외에는 nil을 반환하는 PlanFactory.make(_:)를 완성하세요.

제공된 코드는 plan,users 형식의 줄을 읽고 team for 12 users: 120, free does not allow 5 users 또는 unknown plan: gold를 출력합니다.

코드는 Plan.swift, Free.swift, Team.swift, Enterprise.swift 및 PlanFactory.swift에 작성하세요. main.swift에는 제공된 입력/출력 코드가 있으며 수정할 수 없습니다.

직접 해보기

// 제공된 입력/출력 코드: 그대로 유지하세요
var input: [String] = []
while let line = readLine() { input.append(line) }
for line in input {
    let p = line.split(separator: ",").map(String.init)
    let users = Int(p[1])!
    guard let plan = PlanFactory.make(p[0]) else {
        print("unknown plan: \(p[0])")
        continue
    }
    let price = plan.price(forUsers: users)
    print(price < 0 ? "\(plan.name) does not allow \(users) users" : "\(plan.name) for \(users) users: \(price)")
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨

직접 연습해 보세요: Swift 플레이그라운드