전략 패턴
Coddy GDScript 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 65개 중 49번째.
Strategy 패턴은 알고리즘의 각 버전을 별도의 객체에 넣으므로, 프로그램이 실행되는 동안 알고리즘을 바꿔 사용할 수 있습니다. 이를 사용하는 객체인 컨텍스트는 하나의 메서드를 호출하며, 어떤 버전을 가지고 있는지는 신경 쓰지 않습니다.
두 가지 공격 전략, 부모 클래스와 동일한 메서드 damage()를 가진 하위 클래스가 있습니다:
# attack_style.gd
class_name AttackStyle
extends RefCounted
func damage(power: int) -> int:
return power# heavy_attack.gd
class_name HeavyAttack
extends AttackStyle
func damage(power: int) -> int:
return power * 2컨텍스트는 전략을 저장하고 계산을 전략에 맡깁니다:
# fighter.gd
class_name Fighter
extends RefCounted
var power := 10
var style: AttackStyle = AttackStyle.new()
func set_style(new_style: AttackStyle) -> void:
style = new_style
func attack() -> void:
print("Hit for ", style.damage(power))# main.gd
var fighter := Fighter.new()
fighter.attack()
fighter.set_style(HeavyAttack.new())
fighter.attack()Hit for 10
Hit for 20Fighter는 자신이 어떤 스타일을 가지고 있는지 확인하지 않습니다. 새로운 스타일은 새로운 클래스이며, fighter.gd는 그대로 둡니다. attack() 안의 if style == "heavy" 체인은 스타일이 추가될 때마다 길어집니다.
전략이 자체 데이터가 없는 작은 함수 하나라면 Callable이면 충분합니다. 컨텍스트는 함수를 저장하고 call()로 실행합니다:
# price_calculator.gd
class_name PriceCalculator
extends RefCounted
var discount: Callable = func(price): return price
func final_price(price: int) -> int:
return discount.call(price)# main.gd
var calc := PriceCalculator.new()
print(calc.final_price(80))
calc.discount = func(price): return price / 2
print(calc.final_price(80))
calc.discount = func(price): return max(price - 25, 0)
print(calc.final_price(80))80
40
55전략에 자체 설정이나 여러 메서드가 있을 때는 클래스를 사용하고, 짧은 계산 하나에는 Callables를 사용하세요. 이 아이디어는 이전에도 사용한 적이 있습니다. sort_custom()에 전달하는 비교 함수는 정렬 전략입니다.
챌린지
중급상점 장바구니는 결제 시 할인 전략을 바꿀 수 있습니다. discount.gd의 Discount는 기본 전략입니다. 할인은 없습니다. 전략 두 가지와 장바구니를 작성하세요:
PercentOff(퍼센트로 생성):apply(total)은total - total * percent / 100(정수 연산)을 반환하고, 10퍼센트일 때label()은10% off를 반환합니다.FixedOff(금액으로 생성):apply(total)은 총액에서 금액을 뺀 값을 반환하되, 결과는0보다 작지 않으며, 금액이 30일 때label()은30 off를 반환합니다.Cart:set_discount(new_discount)는 전략을 저장하고,checkout()은 가격을 모두 더한 뒤Subtotal TOTAL, LABEL, pay PRICE를 반환합니다. 여기서 PRICE는 전략의apply()가 반환하는 값입니다.
제공된 코드는 한 줄에서 가격을 읽고, 이어지는 결제 횟수와 각 줄의 전략을 읽습니다: percent N, fixed N 또는 none. 가격이 50 30 40이고 전략이 percent 10, fixed 30, none일 때 출력은 다음과 같습니다:
Subtotal 120, 10% off, pay 108
Subtotal 120, 30 off, pay 90
Subtotal 120, no discount, pay 120코드는 cart.gd, percent_off.gd, fixed_off.gd에 작성하세요. main.gd에는 제공된 입력/출력 코드가 있으며 수정할 수 없습니다.
직접 해보기
extends Node
func _ready():
# 제공된 입출력 코드: 그대로 두세요
var cart := Cart.new()
for price in OS.read_string_from_stdin().split(" "):
cart.add_item(int(price))
var count := int(OS.read_string_from_stdin())
for i in count:
var parts := OS.read_string_from_stdin().split(" ")
if parts[0] == "percent":
cart.set_discount(PercentOff.new(int(parts[1])))
elif parts[0] == "fixed":
cart.set_discount(FixedOff.new(int(parts[1])))
else:
cart.set_discount(Discount.new())
print(cart.checkout())
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 GDScript 컴파일러