데코레이터 패턴
Coddy GDScript 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨. 65개 중 52번째.
데코레이터 패턴은 같은 메서드를 가진 다른 객체로 객체를 감싸 동작을 추가합니다. 각 래퍼는 내부의 객체를 호출하고 자신의 기능을 더하며, 래퍼는 어떤 순서로든 쌓을 수 있습니다.
# weapon.gd
class_name Weapon
extends RefCounted
func get_damage() -> int:
return 10
func describe() -> String:
return "Sword"데코레이터는 Weapon을 확장하므로 무기가 필요한 곳이라면 어디든 사용할 수 있으며, 감싸고 있는 무기를 보유합니다:
# fire_enchant.gd
class_name FireEnchant
extends Weapon
var inner: Weapon
func _init(wrapped: Weapon) -> void:
inner = wrapped
func get_damage() -> int:
return inner.get_damage() + 5
func describe() -> String:
return inner.describe() + " + Fire"SharpEnchant도 같은 방식으로 작성되지만, get_damage()는 inner.get_damage() * 2를 반환하고 describe()는 " + Sharp"를 추가합니다.
# main.gd
var weapon: Weapon = Weapon.new()
print(weapon.describe(), ": ", weapon.get_damage())
weapon = FireEnchant.new(weapon)
weapon = SharpEnchant.new(weapon)
print(weapon.describe(), ": ", weapon.get_damage())Sword: 10
Sword + Fire + Sharp: 30호출은 안쪽으로 전달됩니다. SharpEnchant는 FireEnchant에 요청하고, FireEnchant는 검에 요청합니다. 검은 10을 반환하고, 화염이 이를 15로 만들며, 날카로움이 두 배로 늘려 30이 됩니다. 순서를 바꾸면 FireEnchant.new(SharpEnchant.new(Weapon.new())) 피해량은 10 * 2 + 5이며, 이는 25입니다.
데코레이터가 없다면 모든 조합마다 자체 하위 클래스를 만들어야 합니다: FireSword, SharpSword, FireSharpSword 등등. 데코레이터를 사용하면 작은 클래스 두 개로 모든 조합을 처리할 수 있고, 새로운 인챈트는 파일 하나만 추가하면 됩니다.
챌린지
중급커피숍은 데코레이터를 사용해 음료를 만듭니다. Beverage(beverage.gd)는 cost()와 description()을 선언하며, Espresso(espresso.gd, $3)와 Tea(tea.gd, $2)는 이미 작성되어 있습니다. 각 데코레이터는 감싸고 있는 음료를 inner에 저장합니다(생성자는 이미 작성되어 있습니다). 다음 클래스에서 cost()와 description()을 오버라이드하세요.
Milk: 비용이1더 들며 설명에+ Milk를 추가합니다.Mocha: 비용이2더 들며 설명에+ Mocha를 추가합니다.Large: 내부의 모든 항목의 비용을 두 배로 하고 설명 앞에Large를 붙입니다.
제공된 코드는 뒤따르는 주문의 개수를 읽은 다음, 한 줄에 하나씩 주문을 읽습니다. 주문은 음료(espresso 또는 tea)와 추가 항목으로 구성되며, 추가 항목은 왼쪽에서 오른쪽 순서로 적용됩니다. espresso milk large와 tea mocha milk의 출력은 다음과 같습니다.
Large Espresso + Milk: $8
Tea + Mocha + Milk: $5코드는 milk.gd, mocha.gd, large.gd에 작성하세요. main.gd에는 제공된 입력/출력 코드가 들어 있으며 수정할 수 없습니다.
직접 해보기
extends Node
func _ready():
# 제공된 입력/출력 코드: 그대로 유지하세요
var count := int(OS.read_string_from_stdin())
for i in count:
var words := OS.read_string_from_stdin().split(" ")
var drink: Beverage = Tea.new()
if words[0] == "espresso":
drink = Espresso.new()
for extra in words.slice(1):
match extra:
"milk":
drink = Milk.new(drink)
"mocha":
drink = Mocha.new(drink)
"large":
drink = Large.new(drink)
print("%s: $%d" % [drink.description(), drink.cost()])
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.
객체 지향 프로그래밍의 모든 레슨
직접 연습해 보세요: 온라인 GDScript 컴파일러