Menu
Coddy logo textTech

팩토리 패턴

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 107개 중 87번째.

팩토리 패턴(Factory pattern)은 객체 생성을 별도의 함수나 메서드에 위임하여, 생성 로직을 노출하지 않고도 인스턴스를 생성할 수 있게 해줍니다. 인스턴스 개수를 제어하는 싱글톤(Singleton)과 달리, 팩토리는 입력 매개변수에 기반한 유연한 객체 생성에 집중합니다.

Go에서 팩토리는 일반적으로 인터페이스 타입을 반환하는 함수로, 통합된 API를 통해 서로 다른 구체적인 타입을 생성할 수 있게 해줍니다:

type Notifier interface {
    Send(message string) string
}

type EmailNotifier struct{}
type SMSNotifier struct{}

func (e EmailNotifier) Send(message string) string {
    return "Email: " + message
}

func (s SMSNotifier) Send(message string) string {
    return "SMS: " + message
}

func NewNotifier(notifierType string) Notifier {
    switch notifierType {
    case "email":
        return EmailNotifier{}
    case "sms":
        return SMSNotifier{}
    default:
        return EmailNotifier{}
    }
}

팩토리 함수 NewNotifier는 어떤 구체적인 타입을 생성할지에 대한 결정을 캡슐화합니다. 클라이언트 코드는 Notifier 인터페이스하고만 동작하며, 구체적인 구현에 대해서는 알지 못합니다:

notifier := NewNotifier("sms")
result := notifier.Send("Hello!")  // "SMS: Hello!"

이 패턴은 런타임 조건에 따라 객체를 생성해야 하거나, 복잡한 초기화 로직을 중앙 집중화하고 싶을 때, 또는 클라이언트 코드를 수정하지 않고 새로운 타입을 쉽게 추가해야 할 때 유용합니다. 인터페이스를 구현하는 새로운 구조체(struct)를 추가하고 팩토리 함수(factory function)를 업데이트하기만 하면 됩니다.

challenge icon

챌린지

쉬움

팩토리 패턴을 사용하여 문서 변환기 시스템을 구축해 봅시다! 대상 형식에 따라 서로 다른 문서 변환기를 생성하는 팩토리를 만들어, 클라이언트 코드가 통합된 인터페이스를 통해 모든 변환기와 작업할 수 있도록 할 것입니다.

코드는 두 개의 파일로 구성됩니다:

  • converter.go: 변환기 인터페이스와 구체적인 구현체를 정의합니다.

    문서 내용을 받아 변환된 출력을 반환하는 Convert(content string) string 메서드를 가진 Converter 인터페이스를 생성하세요.

    세 가지 변환기 타입을 구현하세요:

    • PDFConverterConvert 메서드는 PDF: [content]를 반환합니다.
    • HTMLConverterConvert 메서드는 HTML: <p>[content]</p>를 반환합니다.
    • MarkdownConverterConvert 메서드는 MD: # [content]를 반환합니다.

    형식 문자열(pdf, html, 또는 markdown)에 따라 적절한 변환기를 반환하는 팩토리 함수 NewConverter(format string) Converter를 생성하세요. 인식되지 않는 형식의 경우, 기본값으로 PDFConverter를 반환하세요.

  • main.go: 팩토리를 사용하여 변환기를 생성하고 문서를 처리합니다.

    형식 타입과 문서 내용을 읽습니다. 팩토리를 사용하여 적절한 변환기를 생성한 다음, 내용을 변환하고 결과를 출력하세요.

다음 입력이 제공됩니다:

  • 줄 1: 형식 타입 (pdf, html, markdown 또는 기타)
  • 줄 2: 변환할 문서 내용

예를 들어, 다음과 같이 주어지면:

html
Welcome to Go Programming

출력은 다음과 같아야 합니다:

HTML: <p>Welcome to Go Programming</p>

그리고 다음과 같이 주어지면:

markdown
Chapter One

출력은 다음과 같아야 합니다:

MD: # Chapter One

그리고 다음과 같이 주어지면:

pdf
Annual Report 2024

출력은 다음과 같아야 합니다:

PDF: Annual Report 2024

그리고 다음과 같이 주어지면:

docx
Meeting Notes

출력은 다음과 같아야 합니다:

PDF: Meeting Notes

메인 코드가 특정 변환기 타입에 대해 알 필요가 없다는 점에 주목하세요. 단지 팩토리에 변환기를 요청하고 인터페이스를 사용할 뿐입니다. 이를 통해 나중에 클라이언트 코드를 변경하지 않고도 새로운 형식을 쉽게 추가할 수 있습니다!

치트 시트

팩토리 패턴(Factory pattern)은 객체 생성을 별도의 함수에 위임하여, 생성 로직을 노출하지 않고도 인스턴스를 생성할 수 있게 해줍니다. 이 패턴은 입력 매개변수를 기반으로 한 유연한 객체 생성에 초점을 맞춥니다.

팩토리 함수는 인터페이스 타입을 반환하여, 통일된 API를 통해 서로 다른 구체적인 타입들을 생성할 수 있도록 합니다:

type Notifier interface {
    Send(message string) string
}

type EmailNotifier struct{}
type SMSNotifier struct{}

func (e EmailNotifier) Send(message string) string {
    return "Email: " + message
}

func (s SMSNotifier) Send(message string) string {
    return "SMS: " + message
}

func NewNotifier(notifierType string) Notifier {
    switch notifierType {
    case "email":
        return EmailNotifier{}
    case "sms":
        return SMSNotifier{}
    default:
        return EmailNotifier{}
    }
}

클라이언트 코드는 인터페이스하고만 상호작용하며, 구체적인 구현체에 대해서는 알지 못합니다:

notifier := NewNotifier("sms")
result := notifier.Send("Hello!")  // "SMS: Hello!"

이 패턴은 런타임 조건에 따라 객체를 생성해야 하거나, 복잡한 초기화 로직을 중앙 집중화하고 싶을 때, 또는 클라이언트 코드를 수정하지 않고 새로운 타입을 추가해야 할 때 유용합니다.

직접 해보기

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	
	// 포맷 타입 읽기
	scanner.Scan()
	format := scanner.Text()
	
	// 문서 내용 읽기
	scanner.Scan()
	content := scanner.Text()
	
	// TODO: factory를 사용하여 적절한 converter 생성하기
	// TODO: 내용을 변환하고 결과 출력하기
	
	fmt.Println(result)
}
quiz icon실력 점검

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

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