Menu
Coddy logo textTech

전략 패턴

Coddy GO 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 107개 중 90번째.

Strategy 패턴을 사용하면 알고리즘의 family를 정의하고, 각각을 캡슐화하며, 런타임에 서로 interchangeable하게 만들 수 있습니다. 여러 객체가 하나의 이벤트에 반응하는 Observer와 달리, Strategy를 사용하면 단일 객체가 서로 다른 동작 간에 동적으로 전환할 수 있습니다.

Go에서는 알고리즘을 위한 interface를 정의하고 서로 다른 구현을 context 구조체에 주입하여 전략 패턴을 구현합니다:

type PaymentStrategy interface {
    Pay(amount float64) string
}

type CreditCard struct{}
func (c CreditCard) Pay(amount float64) string {
    return fmt.Sprintf("Paid %.2f via Credit Card", amount)
}

type PayPal struct{}
func (p PayPal) Pay(amount float64) string {
    return fmt.Sprintf("Paid %.2f via PayPal", amount)
}

context 구조체는 전략 interface에 대한 참조를 holds하여, context의 코드를 변경하지 않고 알고리즘을 교체할 수 있게 합니다:

type Checkout struct {
    strategy PaymentStrategy
}

func (c *Checkout) SetStrategy(s PaymentStrategy) {
    c.strategy = s
}

func (c *Checkout) ProcessPayment(amount float64) string {
    return c.strategy.Pay(amount)
}

이제 런타임에 결제 방법을 변경할 수 있습니다:

checkout := &Checkout{}

checkout.SetStrategy(CreditCard{})
fmt.Println(checkout.ProcessPayment(100.00))  // Credit Card로 100.00 지불됨

checkout.SetStrategy(PayPal{})
fmt.Println(checkout.ProcessPayment(50.00))   // PayPal로 50.00 지불됨

Strategy는 작업을 수행하는 여러 방법이 있고 사용자 입력, 구성 또는 런타임 조건에 따라 그중 하나를 선택해야 할 때 이상적입니다. 일반적인 사용 사례로는 정렬 알고리즘, 압축 방법 및 유효성 검사 규칙이 있습니다.

challenge icon

챌린지

쉬움

Strategy 패턴을 사용하여 텍스트 formatting 시스템을 만들어 봅시다! 런타임에 교체할 수 있는 다양한 formatting strategy를 만들 것이므로, 핵심 코드를 변경하지 않고도 동일한 텍스트 processor가 서로 다른 출력 스타일을 생성할 수 있습니다.

코드를 세 개의 파일로 구성합니다:

  • formatter.go: strategy interface와 구체적인 formatting strategy를 Define합니다.

    TextFormatter interface와 strategy의 규칙에 따라 텍스트를 변환하는 Format(text string) string method를 만듭니다.

    세 가지 formatting strategy를 Implement합니다:

    • UppercaseFormatter: 텍스트를 모두 대문자로 converts
    • SnakeCaseFormatter: 공백을 밑줄로 converts하고 텍스트를 lowercase로 makes
    • TitleFormatter: 각 단어의 first letter를 capitalizes합니다 (단어는 공백으로 구분됩니다)
  • processor.go: formatting strategy를 사용하는 context struct를 Create합니다.

    TextFormatter strategy를 holds하는 TextProcessor struct를 만듭니다. 다음 method를 추가합니다:

    • SetFormatter(f TextFormatter): active formatting strategy를 변경합니다
    • Process(text string) string: current formatter를 텍스트에 applies합니다

    또한 initial formatter가 설정되지 않은 processor를 반환하는 NewTextProcessor() constructor를 Create합니다.

  • main.go: 런타임에 strategy를 전환하는 방법을 보여 줍니다.

    텍스트 한 줄을 읽은 다음 format operations의 count를 읽습니다. 각 operation에 대해 format type(upper, snake 또는 title)을 읽고, appropriate formatter를 processor에 설정한 뒤 original text를 Process하고 결과를 print합니다.

다음 입력이 제공됩니다:

  • 1번째 줄: formatting할 텍스트
  • 2번째 줄: format operations의 number
  • 이후 줄: 각 operation의 format type

예를 들어 다음이 주어졌을 때:

hello world today
3
upper
snake
title

출력은 다음과 같아야 합니다:

HELLO WORLD TODAY
hello_world_today
Hello World Today

그리고 다음이 주어졌을 때:

Go Programming Language
2
snake
upper

출력은 다음과 같아야 합니다:

go_programming_language
GO PROGRAMMING LANGUAGE

그리고 다음이 주어졌을 때:

design patterns are useful
1
title

출력은 다음과 같아야 합니다:

Design Patterns Are Useful

동일한 TextProcessor가 formatter strategy만 교체하여 완전히 다른 출력을 생성하는 것을 확인하세요. processor는 어떤 specific formatter를 사용하는지 알거나 신경 쓰지 않습니다. 단지 현재 설정된 strategy에 작업을 delegates합니다!

직접 해보기

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// 포맷할 텍스트 읽기
	text, _ := reader.ReadString('\n')
	text = strings.TrimSpace(text)
	
	// 작업 횟수 읽기
	countStr, _ := reader.ReadString('\n')
	count, _ := strconv.Atoi(strings.TrimSpace(countStr))
	
	// 새 텍스트 프로세서 생성
	processor := NewTextProcessor()
	
	// 각 포맷 작업 처리
	for i := 0; i < count; i++ {
		formatType, _ := reader.ReadString('\n')
		formatType = strings.TrimSpace(formatType)
		
		// TODO: formatType ("upper", "snake", 또는 "title")에 따라,
		// 프로세서에 적절한 포맷터를 설정하고
		// 처리된 텍스트를 출력합니다
		
	}
}
quiz icon실력 점검

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

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

직접 연습해 보세요: 온라인 Go 컴파일러