Menu
Coddy logo textTech

팩토리 패턴

Coddy C# 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 70개 중 53번째.

팩토리 패턴(Factory pattern)은 객체 생성을 별도의 메서드나 클래스에 위임하는 생성 패턴입니다. 코드에서 new를 직접 사용하는 대신, 팩토리에 객체 생성을 요청합니다. 이는 생성 로직을 중앙 집중화하고 코드를 더 유연하게 만듭니다.

다양한 유형의 문서를 생성해야 하는 시나리오를 생각해 봅시다. 팩토리가 없으면 코드가 특정 클래스에 밀접하게 결합됩니다:

// 팩토리 미사용 - 분산된 생성 로직
IDocument doc;
if (type == "pdf")
    doc = new PdfDocument();
else if (type == "word")
    doc = new WordDocument();

팩토리는 이러한 의사 결정을 한 곳에서 캡슐화합니다:

public interface IDocument
{
    void Open();
}

public class PdfDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening PDF");
}

public class WordDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening Word");
}

public class DocumentFactory
{
    public IDocument Create(string type)
    {
        return type switch
        {
            "pdf" => new PdfDocument(),
            "word" => new WordDocument(),
            _ => throw new ArgumentException("Unknown type")
        };
    }
}

이제 클라이언트 코드는 구체적인 클래스를 알지 못해도 필요한 것을 단순히 요청하기만 하면 됩니다:

var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open();  // PDF를 여는 중

팩토리 패턴은 나중에 새로운 타입을 추가해야 할 때 빛을 발합니다. SpreadsheetDocument를 추가하려면 문서가 생성되는 모든 곳이 아니라 팩토리에서만 변경하면 됩니다. 이러한 분리는 코드베이스를 유지 관리하고 테스트하기 더 쉽게 만들어 줍니다.

challenge icon

챌린지

쉬움

팩토리 패턴을 사용하여 알림 시스템을 구축해 보겠습니다. 코드 전체에서 다양한 알림 유형을 직접 생성하는 대신, 단순한 문자열 식별자를 기반으로 어떤 알림을 생성할지 결정하는 팩토리 클래스에 생성 로직을 중앙 집중화합니다.

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

  • Notification.cs: Notifications 네임스페이스에 문자열을 반환하는 단일 메서드 Send(string message)를 가진 INotification 인터페이스를 정의합니다. 그런 다음 이 인터페이스를 구현하는 세 개의 클래스를 만듭니다:
    • EmailNotification - "Email: {message}"를 반환합니다.
    • SmsNotification - "SMS: {message}"를 반환합니다.
    • PushNotification - "Push: {message}"를 반환합니다.
  • NotificationFactory.cs: 동일한 네임스페이스에 type 문자열에 따라 적절한 INotification을 반환하는 Create(string type) 메서드를 가진 NotificationFactory 클래스를 만듭니다:
    • "email"EmailNotification을 반환합니다.
    • "sms"SmsNotification을 반환합니다.
    • "push"PushNotification을 반환합니다.
    인식되지 않는 유형의 경우, 기본값으로 EmailNotification을 반환합니다.
  • Program.cs: 팩토리 인스턴스를 생성하고 이를 사용하여 입력에 따라 알림을 생성함으로써 모든 것을 하나로 묶습니다. 팩토리는 어떤 구체 클래스를 인스턴스화할지에 대한 모든 의사 결정을 처리합니다.

두 개의 입력을 받게 됩니다:

  • 알림 유형 (예: sms)
  • 전송할 메시지 (예: Your order has shipped)

팩토리를 사용하여 적절한 알림 유형을 생성한 다음, 메시지와 함께 Send 메서드를 호출하고 결과를 출력하세요.

예를 들어, 입력이 pushMeeting in 5 minutes라면 출력은 다음과 같아야 합니다:

Push: Meeting in 5 minutes

메인 코드가 new EmailNotification() 또는 이와 유사한 코드를 절대 사용하지 않고, 단순히 팩토리에 필요한 것을 요청하는 방식에 주목하세요. 나중에 SlackNotification을 추가하더라도, 알림을 생성하는 모든 곳을 수정할 필요 없이 팩토리만 업데이트하면 됩니다!

치트 시트

팩토리 패턴(Factory pattern)은 객체 생성을 별도의 메서드나 클래스에 위임하여 생성 로직을 중앙 집중화하고 코드를 더 유연하게 만드는 생성 패턴입니다.

팩토리가 없으면 객체 생성이 분산되고 결합도가 높아집니다:

// 팩토리 없음 - 분산된 생성 로직
IDocument doc;
if (type == "pdf")
    doc = new PdfDocument();
else if (type == "word")
    doc = new WordDocument();

팩토리를 사용하면 생성 로직이 한 곳에 캡슐화됩니다:

public interface IDocument
{
    void Open();
}

public class PdfDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening PDF");
}

public class WordDocument : IDocument
{
    public void Open() => Console.WriteLine("Opening Word");
}

public class DocumentFactory
{
    public IDocument Create(string type)
    {
        return type switch
        {
            "pdf" => new PdfDocument(),
            "word" => new WordDocument(),
            _ => throw new ArgumentException("Unknown type")
        };
    }
}

클라이언트 코드는 구체적인 클래스를 알 필요 없이 객체를 요청합니다:

var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open();  // Opening PDF

팩토리 패턴은 새로운 타입을 추가하기 쉽게 만듭니다. 변경 사항이 코드베이스 전체에 흩어지지 않고 팩토리에만 격리됩니다.

직접 해보기

using System;
using Notifications;

class Program
{
    public static void Main(string[] args)
    {
        // 입력 읽기
        string type = Console.ReadLine();
        string message = Console.ReadLine();

        // TODO: NotificationFactory 인스턴스 생성

        // TODO: 팩토리를 사용하여 적절한 알림 생성

        // TODO: Send 메서드를 호출하고 결과 출력
    }
}
quiz icon실력 점검

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

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