Patrón Decorator
Parte de la sección Programación orientada a objetos del Journey de GDScript de Coddy. Lección 52 de 65.
El patrón Decorator añade comportamiento a un objeto envolviéndolo en otro objeto con los mismos métodos. Cada envoltorio llama al objeto que contiene y añade su propia parte, y los envoltorios pueden apilarse en cualquier orden.
# weapon.gd
class_name Weapon
extends RefCounted
func get_damage() -> int:
return 10
func describe() -> String:
return "Sword"Un decorador extiende Weapon, así que puede ocupar el lugar de cualquier arma y contiene el arma que envuelve:
# 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 se escribe de la misma manera, pero su método get_damage() devuelve inner.get_damage() * 2 y su método describe() añade " + 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: 30Las llamadas avanzan hacia dentro: SharpEnchant consulta a FireEnchant, que consulta a la espada. La espada devuelve 10, el fuego lo convierte en 15 y el afilado lo duplica hasta 30. En el otro orden, FireEnchant.new(SharpEnchant.new(Weapon.new())), el daño es 10 * 2 + 5, que es 25.
Sin decoradores, cada combinación necesitaría su propia subclase: FireSword, SharpSword, FireSharpSword y así sucesivamente. Con ellos, dos clases pequeñas cubren todas las combinaciones, y un nuevo encantamiento requiere un archivo más.
Desafío
IntermedioUna cafetería prepara bebidas con decoradores. Beverage (beverage.gd) declara cost() y description(); ya están escritos Espresso (espresso.gd, $3) y Tea (tea.gd, $2). Cada decorador almacena en inner la bebida que envuelve (los constructores ya están escritos). Sobrescribe cost() y description() en:
Milk: cuesta1más y añade+ Milka la descripción.Mocha: cuesta2más y añade+ Mocha.Large: duplica el costo de todo lo que contiene y colocaLargeal principio de la descripción.
El código proporcionado lee cuántos pedidos vienen a continuación y luego un pedido por línea: la bebida (espresso o tea) y sus extras, aplicados de izquierda a derecha. Para espresso milk large y tea mocha milk, la salida es:
Large Espresso + Milk: $8
Tea + Mocha + Milk: $5Tu código va en milk.gd, mocha.gd y large.gd. main.gd contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
extends Node
func _ready():
# Código de entrada/salida proporcionado: mantenlo tal como está
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()])
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Fundamentos de la programación orientada a objetos
Archivos externosIntroducción a la programación orientada a objetosClases vs. objetosLa palabra clave selfMétodosPropiedadesConstructor (_init)Repaso: calculadora sencilla4Polimorfismo
Repaso de la sobrescritura de métodosTipado patoClases y métodos abstractosDiseño de interfacesRepaso: calculadora de formas7Señales
¿Qué es una señal?Declarar y emitirConectarse a las señalesSeñales con argumentosRepaso: sistema de salud10Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite2Propiedades de clase
Variables de instancia y estáticasFunciones estáticasMétodos setter de propiedadesMétodos getter de propiedadesPrivado por convenciónRepaso: administrador de cuentas bancarias5Encapsulación
Miembros públicos y privadosValidación con settersOcultación de informaciónPropiedades de solo lecturaRepaso: sistema de registros de estudiantes8Conceptos avanzados de POO
Composición frente a herenciaClases internasNodos como componentesRefCounted frente a NodeEnums en clases3Herencia
Herencia básicaLa palabra clave superSobrescritura de métodosCadenas de herenciaComprobaciones de tipo con isRepaso: jerarquía de empleados6Métodos especiales
Introducción a los métodos virtualesEl método _to_stringIteradores personalizadosRepaso: lista personalizada9Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de GDScript online