템플릿 메서드 패턴
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 데이터 파싱
// 클라우드에 저장템플릿 메서드(Template Method) 패턴은 여러 클래스가 동일한 알고리즘 구조를 공유하지만 특정 단계에서 차이가 있을 때 사용하기 이상적입니다. 이 패턴은 공통 로직을 기본 클래스에 배치하여 코드 재사용을 촉진하는 동시에, 오버라이드 가능한 메서드를 통해 유연성을 제공합니다.
챌린지
쉬움템플릿 메서드(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는 이를 오버라이드합니다. 이는 템플릿 메서드 패턴을 통해 어떤 단계가 필수적으로 오버라이드되어야 하는지, 어떤 단계가 선택적으로 맞춤화될 수 있는지를 제어하는 방법을 보여줍니다!
치트 시트
템플릿 메서드 패턴(Template Method pattern)은 알고리즘의 골격을 기본 클래스에서 정의하고, 전체 구조를 변경하지 않고도 하위 클래스에서 특정 단계를 재정의할 수 있도록 합니다.
기본 클래스에는 일련의 단계를 호출하는 "템플릿 메서드"가 포함되어 있습니다. 일부 단계는 추상(abstract) 단계(하위 클래스에서 반드시 구현해야 함)이며, 다른 단계는 가상(virtual) 단계(선택적으로 재정의 가능)일 수 있습니다:
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();
// Reading CSV file
// Parsing CSV data
// Saving to default location
DataProcessor json = new JsonProcessor();
json.Process();
// Reading JSON file
// Parsing JSON data
// Saving to cloud템플릿 메서드 패턴은 여러 클래스가 동일한 알고리즘 구조를 공유하지만 특정 단계가 다른 경우에 이상적입니다. 공통 로직을 기본 클래스에 배치하여 코드 재사용을 촉진하는 동시에 재정의 가능한 메서드를 통해 유연성을 제공합니다.
직접 해보기
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() 메서드를 호출합니다.
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.