Menu
Coddy logo textTech

템플릿 메서드 패턴

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

템플릿 메서드 패턴(Template Method pattern)은 알고리즘의 구조를 기본 클래스에서 정의하고, 전체적인 구조를 변경하지 않으면서 하위 클래스에서 특정 단계를 오버라이드할 수 있도록 하는 행동 패턴입니다. 기본 클래스가 워크플로우를 제어하며, 파생 클래스는 개별 단계를 커스터마이징합니다.

이 패턴은 상속과 추상 메서드를 사용합니다. 기본 클래스에는 일련의 단계를 호출하는 "템플릿 메서드"가 포함되어 있으며, 그 중 일부는 추상적이며 하위 클래스에서 구현되어야 합니다:

public abstract class DataProcessor
{
    // 템플릿 메서드 - 알고리즘 구조를 정의합니다
    public void Process()
    {
        ReadData();
        ProcessData();
        SaveData();
    }
    
    protected abstract void ReadData();
    protected abstract void ProcessData();
    protected virtual void SaveData() => Console.WriteLine("Saving to default location");
}

public class CsvProcessor : DataProcessor
{
    protected override void ReadData() => Console.WriteLine("Reading CSV file");
    protected override void ProcessData() => Console.WriteLine("Parsing CSV data");
}

public class JsonProcessor : DataProcessor
{
    protected override void ReadData() => Console.WriteLine("Reading JSON file");
    protected override void ProcessData() => Console.WriteLine("Parsing JSON data");
    protected override void SaveData() => Console.WriteLine("Saving to cloud");
}

각 서브클래스는 자체적인 구현을 제공하는 한편, 베이스 클래스는 작업 순서를 강제합니다:

DataProcessor csv = new CsvProcessor();
csv.Process();
// CSV 파일 읽기
// CSV 데이터 파싱하기
// 기본 위치에 저장하기

DataProcessor json = new JsonProcessor();
json.Process();
// JSON 파일 읽기
// JSON 데이터 파싱하기
// 클라우드에 저장하기

템플릿 메서드 패턴은 여러 클래스가 동일한 알고리즘 구조를 공유하지만 특정 단계에서 차이가 있을 때 사용하기 이상적입니다. 이 패턴은 공통 로직을 기본 클래스에 배치하여 코드 재사용을 촉진하는 동시에, 오버라이드 가능한 메서드를 통해 유연성을 제공합니다.

challenge icon

챌린지

쉬움

템플릿 메서드(Template Method) 패턴을 사용하여 보고서 생성 시스템을 구축해 보겠습니다. 다양한 유형의 보고서(예: 판매 보고서 및 재고 보고서)는 동일한 전체 구조를 공유합니다. 즉, 모두 데이터를 수집하고, 형식을 지정하고, 결과를 출력해야 하지만, 각 보고서 유형마다 이러한 단계를 처리하는 방식이 다릅니다.

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

  • ReportGenerator.cs: Reporting 네임스페이스에 추상 클래스인 ReportGenerator를 생성합니다. 이 기본 클래스는 Generate()라는 템플릿 메서드를 통해 보고서 생성 알고리즘의 골격을 정의합니다. 이 메서드는 GatherData(), FormatReport(), OutputReport()의 세 단계를 순서대로 호출해야 합니다. GatherData()FormatReport()는 추상 메서드로 만들어 각 보고서 유형이 다르게 구현하도록 하고, OutputReport()Sending to default printer를 출력하는 기본 구현을 가진 가상(virtual) 메서드로 만듭니다.
  • ConcreteReports.cs: ReportGenerator를 상속받는 두 개의 구체적인 보고서 클래스를 동일한 네임스페이스에 생성합니다:
    • SalesReport - GatherData()를 구현하여 Collecting sales data from database를 출력하고, FormatReport()를 구현하여 Formatting as sales summary를 출력합니다.
    • InventoryReport - GatherData()를 구현하여 Scanning warehouse inventory를 출력하고, FormatReport()를 구현하여 Formatting as inventory list를 출력하며, OutputReport()를 오버라이드하여 Sending to warehouse manager를 출력합니다.
  • Program.cs: 보고서 인스턴스를 생성하고 실행하여 모든 것을 하나로 묶습니다. 템플릿 메서드는 각 보고서가 동일한 3단계 프로세스를 따르도록 보장하지만, 각 단계의 구체적인 동작은 보고서 유형에 따라 달라집니다.

하나의 입력을 받게 됩니다:

  • 보고서 유형: sales 또는 inventory

입력에 따라 적절한 보고서 생성기를 생성하고 해당 Generate() 메서드를 호출하세요.

예를 들어, 입력이 sales인 경우 출력은 다음과 같아야 합니다:

Collecting sales data from database
Formatting as sales summary
Sending to default printer

입력이 inventory인 경우 출력은 다음과 같아야 합니다:

Scanning warehouse inventory
Formatting as inventory list
Sending to warehouse manager

두 보고서가 정확히 동일한 알고리즘 구조(수집, 형식 지정, 출력)를 따르지만 각 단계의 구현이 어떻게 맞춤화되었는지 확인해 보세요. SalesReport는 기본 출력 동작을 사용하고 InventoryReport는 이를 오버라이드합니다. 이는 템플릿 메서드 패턴을 통해 어떤 단계가 필수적으로 오버라이드되어야 하는지, 어떤 단계가 선택적으로 맞춤화될 수 있는지를 어떻게 제어할 수 있는지 보여줍니다!

직접 해보기

using System;
using Reporting;

class Program
{
    public static void Main(string[] args)
    {
        string reportType = Console.ReadLine();
        
        // TODO: reportType에 따라 적절한 보고서 생성기를 만드세요
        // reportType이 "sales"인 경우, SalesReport를 생성하세요
        // reportType이 "inventory"인 경우, InventoryReport를 생성하세요
        // 그런 다음 보고서에서 Generate() 메서드를 호출하세요
        
    }
}
quiz icon실력 점검

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

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