๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
develop_en/theory

๐ŸŽฏ Template Method Pattern: A Design Pattern That Defines the Skeleton of Algorithms

by JSsunday 2025. 7. 6.
728x90
๋ฐ˜์‘ํ˜•

๐Ÿ“š What is the Template Method Pattern?

The Template Method Pattern is one of the Behavioral Patterns that defines the skeleton of an algorithm in a superclass and allows subclasses to implement specific steps without changing the algorithm's structure.

The core idea of this pattern is to keep the algorithm's structure unchanged while allowing subclasses to redefine certain steps of the algorithm.

๐Ÿ—๏ธ Pattern Structure

The Template Method Pattern consists of the following structure:

  • AbstractClass: Defines the template method and abstract methods
  • ConcreteClass: Implements the abstract methods concretely

๐ŸŽจ Advantages and Disadvantages

โœ… Advantages

  • Improved Code Reusability: Common algorithm structures can be reused
  • Consistency Guarantee: The overall flow of the algorithm remains consistent
  • Easy Maintenance: When common logic needs to be changed, only the superclass needs to be modified

โŒ Disadvantages

  • Inheritance Dependency: Heavily dependent on inheritance relationships
  • Limited Flexibility: Difficult to change the algorithm's structure

๐ŸšŒ Java Example: Bus Operation System

Let's implement a bus operation process using the Template Method Pattern.

// Abstract class: Define the template for bus operations
public abstract class Bus {
    
    // Template method: Define the overall flow of bus operations
    public final void operate() {
        startEngine();
        checkSafety();
        announceRoute();
        driveRoute();
        collectFare();
        stopEngine();
    }
    
    // Common methods
    private void startEngine() {
        System.out.println("๐Ÿ”ฅ Starting the engine.");
    }
    
    private void stopEngine() {
        System.out.println("๐Ÿ›‘ Stopping the engine.");
    }
    
    // Abstract methods - implemented by subclasses
    protected abstract void checkSafety();
    protected abstract void announceRoute();
    protected abstract void driveRoute();
    protected abstract void collectFare();
}

// City bus implementation
public class CityBus extends Bus {
    
    @Override
    protected void checkSafety() {
        System.out.println("๐Ÿ” City bus safety check: Door operation, bell function verification");
    }
    
    @Override
    protected void announceRoute() {
        System.out.println("๐Ÿ“ข Next stop is City Hall Station.");
    }
    
    @Override
    protected void driveRoute() {
        System.out.println("๐ŸšŒ Operating on city roads.");
    }
    
    @Override
    protected void collectFare() {
        System.out.println("๐Ÿ’ณ Please tap your transit card.");
    }
}

// Express bus implementation
public class ExpressBus extends Bus {
    
    @Override
    protected void checkSafety() {
        System.out.println("๐Ÿ” Express bus safety check: Seat belts, emergency exits verification");
    }
    
    @Override
    protected void announceRoute() {
        System.out.println("๐Ÿ“ข This is the Seoul→Busan express bus.");
    }
    
    @Override
    protected void driveRoute() {
        System.out.println("๐Ÿ›ฃ๏ธ Operating on highways.");
    }
    
    @Override
    protected void collectFare() {
        System.out.println("๐ŸŽซ Please show your ticket.");
    }
}

// Usage example
public class BusExample {
    public static void main(String[] args) {
        System.out.println("=== City Bus Operation ===");
        Bus cityBus = new CityBus();
        cityBus.operate();
        
        System.out.println("\n=== Express Bus Operation ===");
        Bus expressBus = new ExpressBus();
        expressBus.operate();
    }
}

โฐ TypeScript Example: Clock System

Let's implement various types of clocks using the Template Method Pattern.

// Abstract class: Define the template for clocks
abstract class Clock {
    
    // Template method: Define the overall flow of clock operations
    public displayTime(): void {
        this.updateTime();
        this.formatTime();
        this.showDisplay();
        this.playSound();
    }
    
    // Common method
    private updateTime(): void {
        console.log("โฑ๏ธ Updating current time.");
    }
    
    // Abstract methods - implemented by subclasses
    protected abstract formatTime(): void;
    protected abstract showDisplay(): void;
    protected abstract playSound(): void;
}

// Digital clock implementation
class DigitalClock extends Clock {
    
    protected formatTime(): void {
        const now = new Date();
        const timeString = now.toLocaleTimeString('en-US', { 
            hour12: false,
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit'
        });
        console.log(`๐Ÿ”ข Digital format: ${timeString}`);
    }
    
    protected showDisplay(): void {
        console.log("๐Ÿ’ป Displaying time on LED display.");
    }
    
    protected playSound(): void {
        console.log("๐Ÿ”Š Beep beep beep! Digital alarm sound");
    }
}

// Analog clock implementation
class AnalogClock extends Clock {
    
    protected formatTime(): void {
        const now = new Date();
        const hours = now.getHours() % 12;
        const minutes = now.getMinutes();
        console.log(`๐Ÿ• Analog format: ${hours} o'clock ${minutes} minutes`);
    }
    
    protected showDisplay(): void {
        console.log("โš™๏ธ Displaying time with hour and minute hands.");
    }
    
    protected playSound(): void {
        console.log("๐Ÿ”” Ding ding ding! Clock chimes");
    }
}

// Smart watch implementation
class SmartWatch extends Clock {
    
    protected formatTime(): void {
        const now = new Date();
        const timeString = now.toLocaleString('en-US', {
            year: 'numeric',
            month: '2-digit',
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit'
        });
        console.log(`๐Ÿ“ฑ Smart format: ${timeString}`);
    }
    
    protected showDisplay(): void {
        console.log("๐Ÿ“บ Displaying time with various information on OLED screen.");
    }
    
    protected playSound(): void {
        console.log("๐ŸŽต Custom notification sound");
    }
}

// Usage example
class ClockExample {
    static run(): void {
        console.log("=== Digital Clock ===");
        const digitalClock = new DigitalClock();
        digitalClock.displayTime();
        
        console.log("\n=== Analog Clock ===");
        const analogClock = new AnalogClock();
        analogClock.displayTime();
        
        console.log("\n=== Smart Watch ===");
        const smartWatch = new SmartWatch();
        smartWatch.displayTime();
    }
}

// Execute
ClockExample.run();

๐ŸŽฏ Use Case Scenarios

The Template Method Pattern is useful in the following situations:

๐Ÿณ Cooking Recipe System

  • When the basic cooking process (preparation→cooking→finishing) is the same, but the specific content of each step differs

๐Ÿ“Š Data Processing Pipeline

  • When the flow of data reading→processing→saving is the same, but the implementation of each step differs

๐ŸŽฎ Game System

  • When the basic game flow (initialization→gameplay→result display) is the same, but the specific logic differs for each game

๐Ÿ’ก Conclusion

The Template Method Pattern is a powerful pattern that provides the skeleton of an algorithm while ensuring flexibility in detailed implementation. It reduces code duplication and maintains consistency while allowing each implementation to have its own characteristics.

This pattern is frequently used in framework development and library design, so it's essential to understand it as one of the core concepts of object-oriented design! ๐Ÿš€


 

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€