Menu
Coddy logo textTech

템플릿 메서드 패턴

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

템플릿 메서드 패턴(Template Method pattern)은 알고리즘의 골격을 기본 클래스에서 정의하여, 하위 클래스가 전체 구조를 변경하지 않고도 특정 단계를 재정의(override)할 수 있도록 합니다. 기본 클래스는 워크플로우를 제어하며, 하위 클래스는 개별 단계를 커스터마이징합니다.

이 패턴은 상속을 사용합니다. 추상 클래스는 일련의 단계를 호출하는 템플릿 메서드를 정의하며, 이 단계 중 일부는 추상적(하위 클래스에서 반드시 구현해야 함)이고 일부는 기본 구현을 가집니다:

abstract class DataProcessor {
  // 템플릿 메서드 - 알고리즘 구조를 정의합니다
  void process() {
    readData();
    processData();
    saveData();
  }

  void readData();      // 추상 메서드 - 하위 클래스에서 반드시 구현해야 함
  void processData();   // 추상 메서드 - 하위 클래스에서 반드시 구현해야 함

  void saveData() {     // 기본 구현
    print('Data saved to database');
  }
}

class CsvProcessor extends DataProcessor {
  @override
  void readData() => print('Reading CSV file');

  @override
  void processData() => print('Parsing CSV rows');
}

class JsonProcessor extends DataProcessor {
  @override
  void readData() => print('Reading JSON file');

  @override
  void processData() => print('Parsing JSON objects');

  @override
  void saveData() => print('Saved to cloud storage');
}

void main() {
  var csv = CsvProcessor();
  csv.process();
  // Reading CSV file
  // Parsing CSV rows
  // Data saved to database

  var json = JsonProcessor();
  json.process();
  // Reading JSON file
  // Parsing JSON objects
  // Saved to cloud storage
}

process() 메서드는 템플릿입니다. 이는 작업의 순서를 정의합니다. 서브클래스는 readData()processData()를 다르게 구현하며, 선택적으로 saveData()를 오버라이드할 수 있습니다. 주요 이점은 개별 단계에서 유연성을 허용하면서도 모든 구현에서 알고리즘의 구조가 일관되게 유지된다는 점입니다.

challenge icon

챌린지

쉬움

템플릿 메서드(Template Method) 패턴을 사용하여 보고서 생성 시스템을 구축해 봅시다! 서로 다른 유형의 보고서가 동일한 전체 구조를 따르되, 각 보고서 유형이 데이터 수집 및 출력 형식 지정과 같은 특정 단계를 사용자 정의하는 프레임워크를 만들 것입니다.

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

  • report_generator.dart: 이 파일에는 추상 베이스 클래스와 구체적인 보고서 구현체가 포함됩니다. ReportGenerator라는 추상 클래스를 만들고, fetchData(), analyzeData(), formatReport(), deliver() 순서로 보고서 생성 워크플로우를 정의하는 generate()라는 템플릿 메서드를 만드세요. fetchData()formatReport() 메서드는 추상 메서드여야 하며(각 보고서 유형마다 다르게 처리함), analyzeData()Analyzing data...를 출력하고 deliver()Report delivered via email.를 출력하도록 기본 구현을 작성하세요. 그 다음 두 개의 구체적인 보고서 클래스를 만드세요:
    • SalesReport - fetchData()Fetching sales data from database...를 출력하고, formatReport()Formatting as bar charts and tables.를 출력합니다.
    • InventoryReport - fetchData()Fetching inventory levels from warehouse...를 출력하고, formatReport()Formatting as inventory list.를 출력하며, deliver()를 오버라이드하여 Report sent to warehouse manager.를 출력합니다.
  • main.dart: 보고서 생성기 파일을 임포트하고 템플릿 메서드 패턴이 알고리즘 구조를 일관되게 유지하면서 어떻게 커스터마이징을 허용하는지 보여주세요. SalesReport를 생성하고 generate() 메서드를 호출하세요. 그런 다음 구분을 위해 빈 줄을 출력하세요. InventoryReport도 생성하고 generate() 메서드를 호출하세요.

두 보고서 모두 동일한 4단계 프로세스를 따르지만, 각 보고서가 특정 목적에 중요한 단계를 어떻게 커스터마이징하는지 확인해 보세요. InventoryReport는 기본 전달 메서드를 오버라이드하여 보고서를 다른 수신자에게 보내기도 합니다!

예상 출력:

Fetching sales data from database...
Analyzing data...
Formatting as bar charts and tables.
Report delivered via email.

Fetching inventory levels from warehouse...
Analyzing data...
Formatting as inventory list.
Report sent to warehouse manager.

치트 시트

템플릿 메서드 패턴(Template Method pattern)은 알고리즘의 골격을 기본 클래스에서 정의하여, 하위 클래스가 전체 구조를 변경하지 않고도 특정 단계를 재정의할 수 있도록 합니다.

추상 클래스는 일련의 단계를 호출하는 템플릿 메서드를 정의합니다. 일부 단계는 추상적(하위 클래스에서 구현해야 함)이며 일부는 기본 구현을 가집니다:

abstract class DataProcessor {
  // 템플릿 메서드 - 알고리즘 구조를 정의합니다
  void process() {
    readData();
    processData();
    saveData();
  }

  void readData();      // 추상 - 하위 클래스에서 구현해야 함
  void processData();   // 추상 - 하위 클래스에서 구현해야 함

  void saveData() {     // 기본 구현
    print('Data saved to database');
  }
}

class CsvProcessor extends DataProcessor {
  @override
  void readData() => print('Reading CSV file');

  @override
  void processData() => print('Parsing CSV rows');
}

class JsonProcessor extends DataProcessor {
  @override
  void readData() => print('Reading JSON file');

  @override
  void processData() => print('Parsing JSON objects');

  @override
  void saveData() => print('Saved to cloud storage');
}

템플릿 메서드는 워크플로 순서를 제어합니다. 하위 클래스는 추상 메서드를 구현하고 선택적으로 기본 구현을 재정의함으로써 개별 단계를 커스터마이징합니다. 알고리즘의 구조는 모든 구현에서 일관되게 유지됩니다.

직접 해보기

import 'report_generator.dart';

void main() {
  // TODO: SalesReport를 생성하고 generate() 메서드를 호출하세요

  // TODO: 구분을 위해 빈 줄을 출력하세요

  // TODO: InventoryReport를 생성하고 generate() 메서드를 호출하세요
}
quiz icon실력 점검

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

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